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 <map>
17*d9f75844SAndroid Build Coastguard Worker #include <string>
18*d9f75844SAndroid Build Coastguard Worker #include <unordered_map>
19*d9f75844SAndroid Build Coastguard Worker #include <utility>
20*d9f75844SAndroid Build Coastguard Worker
21*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
22*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/match.h"
23*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
24*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/crypto_params.h"
26*d9f75844SAndroid Build Coastguard Worker #include "media/base/codec.h"
27*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_constants.h"
28*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_engine.h"
29*d9f75844SAndroid Build Coastguard Worker #include "media/base/sdp_video_format_utils.h"
30*d9f75844SAndroid Build Coastguard Worker #include "media/sctp/sctp_transport_internal.h"
31*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/p2p_constants.h"
32*d9f75844SAndroid Build Coastguard Worker #include "pc/media_protocol_names.h"
33*d9f75844SAndroid Build Coastguard Worker #include "pc/rtp_media_utils.h"
34*d9f75844SAndroid Build Coastguard Worker #include "pc/used_ids.h"
35*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
36*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/helpers.h"
37*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
38*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/ssl_stream_adapter.h"
39*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
40*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/third_party/base64/base64.h"
41*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/unique_id_generator.h"
42*d9f75844SAndroid Build Coastguard Worker
43*d9f75844SAndroid Build Coastguard Worker namespace {
44*d9f75844SAndroid Build Coastguard Worker
45*d9f75844SAndroid Build Coastguard Worker using rtc::UniqueRandomIdGenerator;
46*d9f75844SAndroid Build Coastguard Worker using webrtc::RtpTransceiverDirection;
47*d9f75844SAndroid Build Coastguard Worker
48*d9f75844SAndroid Build Coastguard Worker const char kInline[] = "inline:";
49*d9f75844SAndroid Build Coastguard Worker
GetSupportedSdesCryptoSuiteNames(void (* func)(const webrtc::CryptoOptions &,std::vector<int> *),const webrtc::CryptoOptions & crypto_options,std::vector<std::string> * names)50*d9f75844SAndroid Build Coastguard Worker void GetSupportedSdesCryptoSuiteNames(
51*d9f75844SAndroid Build Coastguard Worker void (*func)(const webrtc::CryptoOptions&, std::vector<int>*),
52*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options,
53*d9f75844SAndroid Build Coastguard Worker std::vector<std::string>* names) {
54*d9f75844SAndroid Build Coastguard Worker std::vector<int> crypto_suites;
55*d9f75844SAndroid Build Coastguard Worker func(crypto_options, &crypto_suites);
56*d9f75844SAndroid Build Coastguard Worker for (const auto crypto : crypto_suites) {
57*d9f75844SAndroid Build Coastguard Worker names->push_back(rtc::SrtpCryptoSuiteToName(crypto));
58*d9f75844SAndroid Build Coastguard Worker }
59*d9f75844SAndroid Build Coastguard Worker }
60*d9f75844SAndroid Build Coastguard Worker
RtpExtensionFromCapability(const webrtc::RtpHeaderExtensionCapability & capability)61*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension RtpExtensionFromCapability(
62*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpHeaderExtensionCapability& capability) {
63*d9f75844SAndroid Build Coastguard Worker return webrtc::RtpExtension(capability.uri,
64*d9f75844SAndroid Build Coastguard Worker capability.preferred_id.value_or(1));
65*d9f75844SAndroid Build Coastguard Worker }
66*d9f75844SAndroid Build Coastguard Worker
RtpHeaderExtensionsFromCapabilities(const std::vector<webrtc::RtpHeaderExtensionCapability> & capabilities)67*d9f75844SAndroid Build Coastguard Worker cricket::RtpHeaderExtensions RtpHeaderExtensionsFromCapabilities(
68*d9f75844SAndroid Build Coastguard Worker const std::vector<webrtc::RtpHeaderExtensionCapability>& capabilities) {
69*d9f75844SAndroid Build Coastguard Worker cricket::RtpHeaderExtensions exts;
70*d9f75844SAndroid Build Coastguard Worker for (const auto& capability : capabilities) {
71*d9f75844SAndroid Build Coastguard Worker exts.push_back(RtpExtensionFromCapability(capability));
72*d9f75844SAndroid Build Coastguard Worker }
73*d9f75844SAndroid Build Coastguard Worker return exts;
74*d9f75844SAndroid Build Coastguard Worker }
75*d9f75844SAndroid Build Coastguard Worker
76*d9f75844SAndroid Build Coastguard Worker std::vector<webrtc::RtpHeaderExtensionCapability>
UnstoppedRtpHeaderExtensionCapabilities(std::vector<webrtc::RtpHeaderExtensionCapability> capabilities)77*d9f75844SAndroid Build Coastguard Worker UnstoppedRtpHeaderExtensionCapabilities(
78*d9f75844SAndroid Build Coastguard Worker std::vector<webrtc::RtpHeaderExtensionCapability> capabilities) {
79*d9f75844SAndroid Build Coastguard Worker capabilities.erase(
80*d9f75844SAndroid Build Coastguard Worker std::remove_if(
81*d9f75844SAndroid Build Coastguard Worker capabilities.begin(), capabilities.end(),
82*d9f75844SAndroid Build Coastguard Worker [](const webrtc::RtpHeaderExtensionCapability& capability) {
83*d9f75844SAndroid Build Coastguard Worker return capability.direction == RtpTransceiverDirection::kStopped;
84*d9f75844SAndroid Build Coastguard Worker }),
85*d9f75844SAndroid Build Coastguard Worker capabilities.end());
86*d9f75844SAndroid Build Coastguard Worker return capabilities;
87*d9f75844SAndroid Build Coastguard Worker }
88*d9f75844SAndroid Build Coastguard Worker
IsCapabilityPresent(const webrtc::RtpHeaderExtensionCapability & capability,const cricket::RtpHeaderExtensions & extensions)89*d9f75844SAndroid Build Coastguard Worker bool IsCapabilityPresent(const webrtc::RtpHeaderExtensionCapability& capability,
90*d9f75844SAndroid Build Coastguard Worker const cricket::RtpHeaderExtensions& extensions) {
91*d9f75844SAndroid Build Coastguard Worker return std::find_if(extensions.begin(), extensions.end(),
92*d9f75844SAndroid Build Coastguard Worker [&capability](const webrtc::RtpExtension& extension) {
93*d9f75844SAndroid Build Coastguard Worker return capability.uri == extension.uri;
94*d9f75844SAndroid Build Coastguard Worker }) != extensions.end();
95*d9f75844SAndroid Build Coastguard Worker }
96*d9f75844SAndroid Build Coastguard Worker
UnstoppedOrPresentRtpHeaderExtensions(const std::vector<webrtc::RtpHeaderExtensionCapability> & capabilities,const cricket::RtpHeaderExtensions & unencrypted,const cricket::RtpHeaderExtensions & encrypted)97*d9f75844SAndroid Build Coastguard Worker cricket::RtpHeaderExtensions UnstoppedOrPresentRtpHeaderExtensions(
98*d9f75844SAndroid Build Coastguard Worker const std::vector<webrtc::RtpHeaderExtensionCapability>& capabilities,
99*d9f75844SAndroid Build Coastguard Worker const cricket::RtpHeaderExtensions& unencrypted,
100*d9f75844SAndroid Build Coastguard Worker const cricket::RtpHeaderExtensions& encrypted) {
101*d9f75844SAndroid Build Coastguard Worker cricket::RtpHeaderExtensions extensions;
102*d9f75844SAndroid Build Coastguard Worker for (const auto& capability : capabilities) {
103*d9f75844SAndroid Build Coastguard Worker if (capability.direction != RtpTransceiverDirection::kStopped ||
104*d9f75844SAndroid Build Coastguard Worker IsCapabilityPresent(capability, unencrypted) ||
105*d9f75844SAndroid Build Coastguard Worker IsCapabilityPresent(capability, encrypted)) {
106*d9f75844SAndroid Build Coastguard Worker extensions.push_back(RtpExtensionFromCapability(capability));
107*d9f75844SAndroid Build Coastguard Worker }
108*d9f75844SAndroid Build Coastguard Worker }
109*d9f75844SAndroid Build Coastguard Worker return extensions;
110*d9f75844SAndroid Build Coastguard Worker }
111*d9f75844SAndroid Build Coastguard Worker
112*d9f75844SAndroid Build Coastguard Worker } // namespace
113*d9f75844SAndroid Build Coastguard Worker
114*d9f75844SAndroid Build Coastguard Worker namespace cricket {
115*d9f75844SAndroid Build Coastguard Worker
NegotiateRtpTransceiverDirection(RtpTransceiverDirection offer,RtpTransceiverDirection wants)116*d9f75844SAndroid Build Coastguard Worker static RtpTransceiverDirection NegotiateRtpTransceiverDirection(
117*d9f75844SAndroid Build Coastguard Worker RtpTransceiverDirection offer,
118*d9f75844SAndroid Build Coastguard Worker RtpTransceiverDirection wants) {
119*d9f75844SAndroid Build Coastguard Worker bool offer_send = webrtc::RtpTransceiverDirectionHasSend(offer);
120*d9f75844SAndroid Build Coastguard Worker bool offer_recv = webrtc::RtpTransceiverDirectionHasRecv(offer);
121*d9f75844SAndroid Build Coastguard Worker bool wants_send = webrtc::RtpTransceiverDirectionHasSend(wants);
122*d9f75844SAndroid Build Coastguard Worker bool wants_recv = webrtc::RtpTransceiverDirectionHasRecv(wants);
123*d9f75844SAndroid Build Coastguard Worker return webrtc::RtpTransceiverDirectionFromSendRecv(offer_recv && wants_send,
124*d9f75844SAndroid Build Coastguard Worker offer_send && wants_recv);
125*d9f75844SAndroid Build Coastguard Worker }
126*d9f75844SAndroid Build Coastguard Worker
IsMediaContentOfType(const ContentInfo * content,MediaType media_type)127*d9f75844SAndroid Build Coastguard Worker static bool IsMediaContentOfType(const ContentInfo* content,
128*d9f75844SAndroid Build Coastguard Worker MediaType media_type) {
129*d9f75844SAndroid Build Coastguard Worker if (!content || !content->media_description()) {
130*d9f75844SAndroid Build Coastguard Worker return false;
131*d9f75844SAndroid Build Coastguard Worker }
132*d9f75844SAndroid Build Coastguard Worker return content->media_description()->type() == media_type;
133*d9f75844SAndroid Build Coastguard Worker }
134*d9f75844SAndroid Build Coastguard Worker
CreateCryptoParams(int tag,const std::string & cipher,CryptoParams * crypto_out)135*d9f75844SAndroid Build Coastguard Worker static bool CreateCryptoParams(int tag,
136*d9f75844SAndroid Build Coastguard Worker const std::string& cipher,
137*d9f75844SAndroid Build Coastguard Worker CryptoParams* crypto_out) {
138*d9f75844SAndroid Build Coastguard Worker int key_len;
139*d9f75844SAndroid Build Coastguard Worker int salt_len;
140*d9f75844SAndroid Build Coastguard Worker if (!rtc::GetSrtpKeyAndSaltLengths(rtc::SrtpCryptoSuiteFromName(cipher),
141*d9f75844SAndroid Build Coastguard Worker &key_len, &salt_len)) {
142*d9f75844SAndroid Build Coastguard Worker return false;
143*d9f75844SAndroid Build Coastguard Worker }
144*d9f75844SAndroid Build Coastguard Worker
145*d9f75844SAndroid Build Coastguard Worker int master_key_len = key_len + salt_len;
146*d9f75844SAndroid Build Coastguard Worker std::string master_key;
147*d9f75844SAndroid Build Coastguard Worker if (!rtc::CreateRandomData(master_key_len, &master_key)) {
148*d9f75844SAndroid Build Coastguard Worker return false;
149*d9f75844SAndroid Build Coastguard Worker }
150*d9f75844SAndroid Build Coastguard Worker
151*d9f75844SAndroid Build Coastguard Worker RTC_CHECK_EQ(master_key_len, master_key.size());
152*d9f75844SAndroid Build Coastguard Worker std::string key = rtc::Base64::Encode(master_key);
153*d9f75844SAndroid Build Coastguard Worker
154*d9f75844SAndroid Build Coastguard Worker crypto_out->tag = tag;
155*d9f75844SAndroid Build Coastguard Worker crypto_out->cipher_suite = cipher;
156*d9f75844SAndroid Build Coastguard Worker crypto_out->key_params = kInline;
157*d9f75844SAndroid Build Coastguard Worker crypto_out->key_params += key;
158*d9f75844SAndroid Build Coastguard Worker return true;
159*d9f75844SAndroid Build Coastguard Worker }
160*d9f75844SAndroid Build Coastguard Worker
AddCryptoParams(const std::string & cipher_suite,CryptoParamsVec * cryptos_out)161*d9f75844SAndroid Build Coastguard Worker static bool AddCryptoParams(const std::string& cipher_suite,
162*d9f75844SAndroid Build Coastguard Worker CryptoParamsVec* cryptos_out) {
163*d9f75844SAndroid Build Coastguard Worker int size = static_cast<int>(cryptos_out->size());
164*d9f75844SAndroid Build Coastguard Worker
165*d9f75844SAndroid Build Coastguard Worker cryptos_out->resize(size + 1);
166*d9f75844SAndroid Build Coastguard Worker return CreateCryptoParams(size, cipher_suite, &cryptos_out->at(size));
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker
AddMediaCryptos(const CryptoParamsVec & cryptos,MediaContentDescription * media)169*d9f75844SAndroid Build Coastguard Worker void AddMediaCryptos(const CryptoParamsVec& cryptos,
170*d9f75844SAndroid Build Coastguard Worker MediaContentDescription* media) {
171*d9f75844SAndroid Build Coastguard Worker for (const CryptoParams& crypto : cryptos) {
172*d9f75844SAndroid Build Coastguard Worker media->AddCrypto(crypto);
173*d9f75844SAndroid Build Coastguard Worker }
174*d9f75844SAndroid Build Coastguard Worker }
175*d9f75844SAndroid Build Coastguard Worker
CreateMediaCryptos(const std::vector<std::string> & crypto_suites,MediaContentDescription * media)176*d9f75844SAndroid Build Coastguard Worker bool CreateMediaCryptos(const std::vector<std::string>& crypto_suites,
177*d9f75844SAndroid Build Coastguard Worker MediaContentDescription* media) {
178*d9f75844SAndroid Build Coastguard Worker CryptoParamsVec cryptos;
179*d9f75844SAndroid Build Coastguard Worker for (const std::string& crypto_suite : crypto_suites) {
180*d9f75844SAndroid Build Coastguard Worker if (!AddCryptoParams(crypto_suite, &cryptos)) {
181*d9f75844SAndroid Build Coastguard Worker return false;
182*d9f75844SAndroid Build Coastguard Worker }
183*d9f75844SAndroid Build Coastguard Worker }
184*d9f75844SAndroid Build Coastguard Worker AddMediaCryptos(cryptos, media);
185*d9f75844SAndroid Build Coastguard Worker return true;
186*d9f75844SAndroid Build Coastguard Worker }
187*d9f75844SAndroid Build Coastguard Worker
GetCryptos(const ContentInfo * content)188*d9f75844SAndroid Build Coastguard Worker const CryptoParamsVec* GetCryptos(const ContentInfo* content) {
189*d9f75844SAndroid Build Coastguard Worker if (!content || !content->media_description()) {
190*d9f75844SAndroid Build Coastguard Worker return nullptr;
191*d9f75844SAndroid Build Coastguard Worker }
192*d9f75844SAndroid Build Coastguard Worker return &content->media_description()->cryptos();
193*d9f75844SAndroid Build Coastguard Worker }
194*d9f75844SAndroid Build Coastguard Worker
FindMatchingCrypto(const CryptoParamsVec & cryptos,const CryptoParams & crypto,CryptoParams * crypto_out)195*d9f75844SAndroid Build Coastguard Worker bool FindMatchingCrypto(const CryptoParamsVec& cryptos,
196*d9f75844SAndroid Build Coastguard Worker const CryptoParams& crypto,
197*d9f75844SAndroid Build Coastguard Worker CryptoParams* crypto_out) {
198*d9f75844SAndroid Build Coastguard Worker auto it = absl::c_find_if(
199*d9f75844SAndroid Build Coastguard Worker cryptos, [&crypto](const CryptoParams& c) { return crypto.Matches(c); });
200*d9f75844SAndroid Build Coastguard Worker if (it == cryptos.end()) {
201*d9f75844SAndroid Build Coastguard Worker return false;
202*d9f75844SAndroid Build Coastguard Worker }
203*d9f75844SAndroid Build Coastguard Worker *crypto_out = *it;
204*d9f75844SAndroid Build Coastguard Worker return true;
205*d9f75844SAndroid Build Coastguard Worker }
206*d9f75844SAndroid Build Coastguard Worker
207*d9f75844SAndroid Build Coastguard Worker // For audio, HMAC 32 (if enabled) is prefered over HMAC 80 because of the
208*d9f75844SAndroid Build Coastguard Worker // low overhead.
GetSupportedAudioSdesCryptoSuites(const webrtc::CryptoOptions & crypto_options,std::vector<int> * crypto_suites)209*d9f75844SAndroid Build Coastguard Worker void GetSupportedAudioSdesCryptoSuites(
210*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options,
211*d9f75844SAndroid Build Coastguard Worker std::vector<int>* crypto_suites) {
212*d9f75844SAndroid Build Coastguard Worker if (crypto_options.srtp.enable_aes128_sha1_32_crypto_cipher) {
213*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAes128CmSha1_32);
214*d9f75844SAndroid Build Coastguard Worker }
215*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAes128CmSha1_80);
216*d9f75844SAndroid Build Coastguard Worker if (crypto_options.srtp.enable_gcm_crypto_suites) {
217*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAeadAes256Gcm);
218*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAeadAes128Gcm);
219*d9f75844SAndroid Build Coastguard Worker }
220*d9f75844SAndroid Build Coastguard Worker }
221*d9f75844SAndroid Build Coastguard Worker
GetSupportedAudioSdesCryptoSuiteNames(const webrtc::CryptoOptions & crypto_options,std::vector<std::string> * crypto_suite_names)222*d9f75844SAndroid Build Coastguard Worker void GetSupportedAudioSdesCryptoSuiteNames(
223*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options,
224*d9f75844SAndroid Build Coastguard Worker std::vector<std::string>* crypto_suite_names) {
225*d9f75844SAndroid Build Coastguard Worker GetSupportedSdesCryptoSuiteNames(GetSupportedAudioSdesCryptoSuites,
226*d9f75844SAndroid Build Coastguard Worker crypto_options, crypto_suite_names);
227*d9f75844SAndroid Build Coastguard Worker }
228*d9f75844SAndroid Build Coastguard Worker
GetSupportedVideoSdesCryptoSuites(const webrtc::CryptoOptions & crypto_options,std::vector<int> * crypto_suites)229*d9f75844SAndroid Build Coastguard Worker void GetSupportedVideoSdesCryptoSuites(
230*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options,
231*d9f75844SAndroid Build Coastguard Worker std::vector<int>* crypto_suites) {
232*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAes128CmSha1_80);
233*d9f75844SAndroid Build Coastguard Worker if (crypto_options.srtp.enable_gcm_crypto_suites) {
234*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAeadAes256Gcm);
235*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAeadAes128Gcm);
236*d9f75844SAndroid Build Coastguard Worker }
237*d9f75844SAndroid Build Coastguard Worker }
238*d9f75844SAndroid Build Coastguard Worker
GetSupportedVideoSdesCryptoSuiteNames(const webrtc::CryptoOptions & crypto_options,std::vector<std::string> * crypto_suite_names)239*d9f75844SAndroid Build Coastguard Worker void GetSupportedVideoSdesCryptoSuiteNames(
240*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options,
241*d9f75844SAndroid Build Coastguard Worker std::vector<std::string>* crypto_suite_names) {
242*d9f75844SAndroid Build Coastguard Worker GetSupportedSdesCryptoSuiteNames(GetSupportedVideoSdesCryptoSuites,
243*d9f75844SAndroid Build Coastguard Worker crypto_options, crypto_suite_names);
244*d9f75844SAndroid Build Coastguard Worker }
245*d9f75844SAndroid Build Coastguard Worker
GetSupportedDataSdesCryptoSuites(const webrtc::CryptoOptions & crypto_options,std::vector<int> * crypto_suites)246*d9f75844SAndroid Build Coastguard Worker void GetSupportedDataSdesCryptoSuites(
247*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options,
248*d9f75844SAndroid Build Coastguard Worker std::vector<int>* crypto_suites) {
249*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAes128CmSha1_80);
250*d9f75844SAndroid Build Coastguard Worker if (crypto_options.srtp.enable_gcm_crypto_suites) {
251*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAeadAes256Gcm);
252*d9f75844SAndroid Build Coastguard Worker crypto_suites->push_back(rtc::kSrtpAeadAes128Gcm);
253*d9f75844SAndroid Build Coastguard Worker }
254*d9f75844SAndroid Build Coastguard Worker }
255*d9f75844SAndroid Build Coastguard Worker
GetSupportedDataSdesCryptoSuiteNames(const webrtc::CryptoOptions & crypto_options,std::vector<std::string> * crypto_suite_names)256*d9f75844SAndroid Build Coastguard Worker void GetSupportedDataSdesCryptoSuiteNames(
257*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options,
258*d9f75844SAndroid Build Coastguard Worker std::vector<std::string>* crypto_suite_names) {
259*d9f75844SAndroid Build Coastguard Worker GetSupportedSdesCryptoSuiteNames(GetSupportedDataSdesCryptoSuites,
260*d9f75844SAndroid Build Coastguard Worker crypto_options, crypto_suite_names);
261*d9f75844SAndroid Build Coastguard Worker }
262*d9f75844SAndroid Build Coastguard Worker
263*d9f75844SAndroid Build Coastguard Worker // Support any GCM cipher (if enabled through options). For video support only
264*d9f75844SAndroid Build Coastguard Worker // 80-bit SHA1 HMAC. For audio 32-bit HMAC is tolerated (if enabled) unless
265*d9f75844SAndroid Build Coastguard Worker // bundle is enabled because it is low overhead.
266*d9f75844SAndroid Build Coastguard Worker // Pick the crypto in the list that is supported.
SelectCrypto(const MediaContentDescription * offer,bool bundle,const webrtc::CryptoOptions & crypto_options,CryptoParams * crypto_out)267*d9f75844SAndroid Build Coastguard Worker static bool SelectCrypto(const MediaContentDescription* offer,
268*d9f75844SAndroid Build Coastguard Worker bool bundle,
269*d9f75844SAndroid Build Coastguard Worker const webrtc::CryptoOptions& crypto_options,
270*d9f75844SAndroid Build Coastguard Worker CryptoParams* crypto_out) {
271*d9f75844SAndroid Build Coastguard Worker bool audio = offer->type() == MEDIA_TYPE_AUDIO;
272*d9f75844SAndroid Build Coastguard Worker const CryptoParamsVec& cryptos = offer->cryptos();
273*d9f75844SAndroid Build Coastguard Worker
274*d9f75844SAndroid Build Coastguard Worker for (const CryptoParams& crypto : cryptos) {
275*d9f75844SAndroid Build Coastguard Worker if ((crypto_options.srtp.enable_gcm_crypto_suites &&
276*d9f75844SAndroid Build Coastguard Worker rtc::IsGcmCryptoSuiteName(crypto.cipher_suite)) ||
277*d9f75844SAndroid Build Coastguard Worker rtc::kCsAesCm128HmacSha1_80 == crypto.cipher_suite ||
278*d9f75844SAndroid Build Coastguard Worker (rtc::kCsAesCm128HmacSha1_32 == crypto.cipher_suite && audio &&
279*d9f75844SAndroid Build Coastguard Worker !bundle && crypto_options.srtp.enable_aes128_sha1_32_crypto_cipher)) {
280*d9f75844SAndroid Build Coastguard Worker return CreateCryptoParams(crypto.tag, crypto.cipher_suite, crypto_out);
281*d9f75844SAndroid Build Coastguard Worker }
282*d9f75844SAndroid Build Coastguard Worker }
283*d9f75844SAndroid Build Coastguard Worker return false;
284*d9f75844SAndroid Build Coastguard Worker }
285*d9f75844SAndroid Build Coastguard Worker
286*d9f75844SAndroid Build Coastguard Worker // Finds all StreamParams of all media types and attach them to stream_params.
GetCurrentStreamParams(const std::vector<const ContentInfo * > & active_local_contents)287*d9f75844SAndroid Build Coastguard Worker static StreamParamsVec GetCurrentStreamParams(
288*d9f75844SAndroid Build Coastguard Worker const std::vector<const ContentInfo*>& active_local_contents) {
289*d9f75844SAndroid Build Coastguard Worker StreamParamsVec stream_params;
290*d9f75844SAndroid Build Coastguard Worker for (const ContentInfo* content : active_local_contents) {
291*d9f75844SAndroid Build Coastguard Worker for (const StreamParams& params : content->media_description()->streams()) {
292*d9f75844SAndroid Build Coastguard Worker stream_params.push_back(params);
293*d9f75844SAndroid Build Coastguard Worker }
294*d9f75844SAndroid Build Coastguard Worker }
295*d9f75844SAndroid Build Coastguard Worker return stream_params;
296*d9f75844SAndroid Build Coastguard Worker }
297*d9f75844SAndroid Build Coastguard Worker
CreateStreamParamsForNewSenderWithSsrcs(const SenderOptions & sender,const std::string & rtcp_cname,bool include_rtx_streams,bool include_flexfec_stream,UniqueRandomIdGenerator * ssrc_generator,const webrtc::FieldTrialsView & field_trials)298*d9f75844SAndroid Build Coastguard Worker static StreamParams CreateStreamParamsForNewSenderWithSsrcs(
299*d9f75844SAndroid Build Coastguard Worker const SenderOptions& sender,
300*d9f75844SAndroid Build Coastguard Worker const std::string& rtcp_cname,
301*d9f75844SAndroid Build Coastguard Worker bool include_rtx_streams,
302*d9f75844SAndroid Build Coastguard Worker bool include_flexfec_stream,
303*d9f75844SAndroid Build Coastguard Worker UniqueRandomIdGenerator* ssrc_generator,
304*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView& field_trials) {
305*d9f75844SAndroid Build Coastguard Worker StreamParams result;
306*d9f75844SAndroid Build Coastguard Worker result.id = sender.track_id;
307*d9f75844SAndroid Build Coastguard Worker
308*d9f75844SAndroid Build Coastguard Worker // TODO(brandtr): Update when we support multistream protection.
309*d9f75844SAndroid Build Coastguard Worker if (include_flexfec_stream && sender.num_sim_layers > 1) {
310*d9f75844SAndroid Build Coastguard Worker include_flexfec_stream = false;
311*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING)
312*d9f75844SAndroid Build Coastguard Worker << "Our FlexFEC implementation only supports protecting "
313*d9f75844SAndroid Build Coastguard Worker "a single media streams. This session has multiple "
314*d9f75844SAndroid Build Coastguard Worker "media streams however, so no FlexFEC SSRC will be generated.";
315*d9f75844SAndroid Build Coastguard Worker }
316*d9f75844SAndroid Build Coastguard Worker if (include_flexfec_stream && !field_trials.IsEnabled("WebRTC-FlexFEC-03")) {
317*d9f75844SAndroid Build Coastguard Worker include_flexfec_stream = false;
318*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING)
319*d9f75844SAndroid Build Coastguard Worker << "WebRTC-FlexFEC trial is not enabled, not sending FlexFEC";
320*d9f75844SAndroid Build Coastguard Worker }
321*d9f75844SAndroid Build Coastguard Worker
322*d9f75844SAndroid Build Coastguard Worker result.GenerateSsrcs(sender.num_sim_layers, include_rtx_streams,
323*d9f75844SAndroid Build Coastguard Worker include_flexfec_stream, ssrc_generator);
324*d9f75844SAndroid Build Coastguard Worker
325*d9f75844SAndroid Build Coastguard Worker result.cname = rtcp_cname;
326*d9f75844SAndroid Build Coastguard Worker result.set_stream_ids(sender.stream_ids);
327*d9f75844SAndroid Build Coastguard Worker
328*d9f75844SAndroid Build Coastguard Worker return result;
329*d9f75844SAndroid Build Coastguard Worker }
330*d9f75844SAndroid Build Coastguard Worker
ValidateSimulcastLayers(const std::vector<RidDescription> & rids,const SimulcastLayerList & simulcast_layers)331*d9f75844SAndroid Build Coastguard Worker static bool ValidateSimulcastLayers(
332*d9f75844SAndroid Build Coastguard Worker const std::vector<RidDescription>& rids,
333*d9f75844SAndroid Build Coastguard Worker const SimulcastLayerList& simulcast_layers) {
334*d9f75844SAndroid Build Coastguard Worker return absl::c_all_of(
335*d9f75844SAndroid Build Coastguard Worker simulcast_layers.GetAllLayers(), [&rids](const SimulcastLayer& layer) {
336*d9f75844SAndroid Build Coastguard Worker return absl::c_any_of(rids, [&layer](const RidDescription& rid) {
337*d9f75844SAndroid Build Coastguard Worker return rid.rid == layer.rid;
338*d9f75844SAndroid Build Coastguard Worker });
339*d9f75844SAndroid Build Coastguard Worker });
340*d9f75844SAndroid Build Coastguard Worker }
341*d9f75844SAndroid Build Coastguard Worker
CreateStreamParamsForNewSenderWithRids(const SenderOptions & sender,const std::string & rtcp_cname)342*d9f75844SAndroid Build Coastguard Worker static StreamParams CreateStreamParamsForNewSenderWithRids(
343*d9f75844SAndroid Build Coastguard Worker const SenderOptions& sender,
344*d9f75844SAndroid Build Coastguard Worker const std::string& rtcp_cname) {
345*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!sender.rids.empty());
346*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(sender.num_sim_layers, 0)
347*d9f75844SAndroid Build Coastguard Worker << "RIDs are the compliant way to indicate simulcast.";
348*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(ValidateSimulcastLayers(sender.rids, sender.simulcast_layers));
349*d9f75844SAndroid Build Coastguard Worker StreamParams result;
350*d9f75844SAndroid Build Coastguard Worker result.id = sender.track_id;
351*d9f75844SAndroid Build Coastguard Worker result.cname = rtcp_cname;
352*d9f75844SAndroid Build Coastguard Worker result.set_stream_ids(sender.stream_ids);
353*d9f75844SAndroid Build Coastguard Worker
354*d9f75844SAndroid Build Coastguard Worker // More than one rid should be signaled.
355*d9f75844SAndroid Build Coastguard Worker if (sender.rids.size() > 1) {
356*d9f75844SAndroid Build Coastguard Worker result.set_rids(sender.rids);
357*d9f75844SAndroid Build Coastguard Worker }
358*d9f75844SAndroid Build Coastguard Worker
359*d9f75844SAndroid Build Coastguard Worker return result;
360*d9f75844SAndroid Build Coastguard Worker }
361*d9f75844SAndroid Build Coastguard Worker
362*d9f75844SAndroid Build Coastguard Worker // Adds SimulcastDescription if indicated by the media description options.
363*d9f75844SAndroid Build Coastguard Worker // MediaContentDescription should already be set up with the send rids.
AddSimulcastToMediaDescription(const MediaDescriptionOptions & media_description_options,MediaContentDescription * description)364*d9f75844SAndroid Build Coastguard Worker static void AddSimulcastToMediaDescription(
365*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
366*d9f75844SAndroid Build Coastguard Worker MediaContentDescription* description) {
367*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(description);
368*d9f75844SAndroid Build Coastguard Worker
369*d9f75844SAndroid Build Coastguard Worker // Check if we are using RIDs in this scenario.
370*d9f75844SAndroid Build Coastguard Worker if (absl::c_all_of(description->streams(), [](const StreamParams& params) {
371*d9f75844SAndroid Build Coastguard Worker return !params.has_rids();
372*d9f75844SAndroid Build Coastguard Worker })) {
373*d9f75844SAndroid Build Coastguard Worker return;
374*d9f75844SAndroid Build Coastguard Worker }
375*d9f75844SAndroid Build Coastguard Worker
376*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(1, description->streams().size())
377*d9f75844SAndroid Build Coastguard Worker << "RIDs are only supported in Unified Plan semantics.";
378*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(1, media_description_options.sender_options.size());
379*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(description->type() == MediaType::MEDIA_TYPE_AUDIO ||
380*d9f75844SAndroid Build Coastguard Worker description->type() == MediaType::MEDIA_TYPE_VIDEO);
381*d9f75844SAndroid Build Coastguard Worker
382*d9f75844SAndroid Build Coastguard Worker // One RID or less indicates that simulcast is not needed.
383*d9f75844SAndroid Build Coastguard Worker if (description->streams()[0].rids().size() <= 1) {
384*d9f75844SAndroid Build Coastguard Worker return;
385*d9f75844SAndroid Build Coastguard Worker }
386*d9f75844SAndroid Build Coastguard Worker
387*d9f75844SAndroid Build Coastguard Worker // Only negotiate the send layers.
388*d9f75844SAndroid Build Coastguard Worker SimulcastDescription simulcast;
389*d9f75844SAndroid Build Coastguard Worker simulcast.send_layers() =
390*d9f75844SAndroid Build Coastguard Worker media_description_options.sender_options[0].simulcast_layers;
391*d9f75844SAndroid Build Coastguard Worker description->set_simulcast_description(simulcast);
392*d9f75844SAndroid Build Coastguard Worker }
393*d9f75844SAndroid Build Coastguard Worker
394*d9f75844SAndroid Build Coastguard Worker // Adds a StreamParams for each SenderOptions in `sender_options` to
395*d9f75844SAndroid Build Coastguard Worker // content_description.
396*d9f75844SAndroid Build Coastguard Worker // `current_params` - All currently known StreamParams of any media type.
397*d9f75844SAndroid Build Coastguard Worker template <class C>
AddStreamParams(const std::vector<SenderOptions> & sender_options,const std::string & rtcp_cname,UniqueRandomIdGenerator * ssrc_generator,StreamParamsVec * current_streams,MediaContentDescriptionImpl<C> * content_description,const webrtc::FieldTrialsView & field_trials)398*d9f75844SAndroid Build Coastguard Worker static bool AddStreamParams(const std::vector<SenderOptions>& sender_options,
399*d9f75844SAndroid Build Coastguard Worker const std::string& rtcp_cname,
400*d9f75844SAndroid Build Coastguard Worker UniqueRandomIdGenerator* ssrc_generator,
401*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
402*d9f75844SAndroid Build Coastguard Worker MediaContentDescriptionImpl<C>* content_description,
403*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView& field_trials) {
404*d9f75844SAndroid Build Coastguard Worker // SCTP streams are not negotiated using SDP/ContentDescriptions.
405*d9f75844SAndroid Build Coastguard Worker if (IsSctpProtocol(content_description->protocol())) {
406*d9f75844SAndroid Build Coastguard Worker return true;
407*d9f75844SAndroid Build Coastguard Worker }
408*d9f75844SAndroid Build Coastguard Worker
409*d9f75844SAndroid Build Coastguard Worker const bool include_rtx_streams =
410*d9f75844SAndroid Build Coastguard Worker ContainsRtxCodec(content_description->codecs());
411*d9f75844SAndroid Build Coastguard Worker
412*d9f75844SAndroid Build Coastguard Worker const bool include_flexfec_stream =
413*d9f75844SAndroid Build Coastguard Worker ContainsFlexfecCodec(content_description->codecs());
414*d9f75844SAndroid Build Coastguard Worker
415*d9f75844SAndroid Build Coastguard Worker for (const SenderOptions& sender : sender_options) {
416*d9f75844SAndroid Build Coastguard Worker StreamParams* param = GetStreamByIds(*current_streams, sender.track_id);
417*d9f75844SAndroid Build Coastguard Worker if (!param) {
418*d9f75844SAndroid Build Coastguard Worker // This is a new sender.
419*d9f75844SAndroid Build Coastguard Worker StreamParams stream_param =
420*d9f75844SAndroid Build Coastguard Worker sender.rids.empty()
421*d9f75844SAndroid Build Coastguard Worker ?
422*d9f75844SAndroid Build Coastguard Worker // Signal SSRCs and legacy simulcast (if requested).
423*d9f75844SAndroid Build Coastguard Worker CreateStreamParamsForNewSenderWithSsrcs(
424*d9f75844SAndroid Build Coastguard Worker sender, rtcp_cname, include_rtx_streams,
425*d9f75844SAndroid Build Coastguard Worker include_flexfec_stream, ssrc_generator, field_trials)
426*d9f75844SAndroid Build Coastguard Worker :
427*d9f75844SAndroid Build Coastguard Worker // Signal RIDs and spec-compliant simulcast (if requested).
428*d9f75844SAndroid Build Coastguard Worker CreateStreamParamsForNewSenderWithRids(sender, rtcp_cname);
429*d9f75844SAndroid Build Coastguard Worker
430*d9f75844SAndroid Build Coastguard Worker content_description->AddStream(stream_param);
431*d9f75844SAndroid Build Coastguard Worker
432*d9f75844SAndroid Build Coastguard Worker // Store the new StreamParams in current_streams.
433*d9f75844SAndroid Build Coastguard Worker // This is necessary so that we can use the CNAME for other media types.
434*d9f75844SAndroid Build Coastguard Worker current_streams->push_back(stream_param);
435*d9f75844SAndroid Build Coastguard Worker } else {
436*d9f75844SAndroid Build Coastguard Worker // Use existing generated SSRCs/groups, but update the sync_label if
437*d9f75844SAndroid Build Coastguard Worker // necessary. This may be needed if a MediaStreamTrack was moved from one
438*d9f75844SAndroid Build Coastguard Worker // MediaStream to another.
439*d9f75844SAndroid Build Coastguard Worker param->set_stream_ids(sender.stream_ids);
440*d9f75844SAndroid Build Coastguard Worker content_description->AddStream(*param);
441*d9f75844SAndroid Build Coastguard Worker }
442*d9f75844SAndroid Build Coastguard Worker }
443*d9f75844SAndroid Build Coastguard Worker return true;
444*d9f75844SAndroid Build Coastguard Worker }
445*d9f75844SAndroid Build Coastguard Worker
446*d9f75844SAndroid Build Coastguard Worker // Updates the transport infos of the `sdesc` according to the given
447*d9f75844SAndroid Build Coastguard Worker // `bundle_group`. The transport infos of the content names within the
448*d9f75844SAndroid Build Coastguard Worker // `bundle_group` should be updated to use the ufrag, pwd and DTLS role of the
449*d9f75844SAndroid Build Coastguard Worker // first content within the `bundle_group`.
UpdateTransportInfoForBundle(const ContentGroup & bundle_group,SessionDescription * sdesc)450*d9f75844SAndroid Build Coastguard Worker static bool UpdateTransportInfoForBundle(const ContentGroup& bundle_group,
451*d9f75844SAndroid Build Coastguard Worker SessionDescription* sdesc) {
452*d9f75844SAndroid Build Coastguard Worker // The bundle should not be empty.
453*d9f75844SAndroid Build Coastguard Worker if (!sdesc || !bundle_group.FirstContentName()) {
454*d9f75844SAndroid Build Coastguard Worker return false;
455*d9f75844SAndroid Build Coastguard Worker }
456*d9f75844SAndroid Build Coastguard Worker
457*d9f75844SAndroid Build Coastguard Worker // We should definitely have a transport for the first content.
458*d9f75844SAndroid Build Coastguard Worker const std::string& selected_content_name = *bundle_group.FirstContentName();
459*d9f75844SAndroid Build Coastguard Worker const TransportInfo* selected_transport_info =
460*d9f75844SAndroid Build Coastguard Worker sdesc->GetTransportInfoByName(selected_content_name);
461*d9f75844SAndroid Build Coastguard Worker if (!selected_transport_info) {
462*d9f75844SAndroid Build Coastguard Worker return false;
463*d9f75844SAndroid Build Coastguard Worker }
464*d9f75844SAndroid Build Coastguard Worker
465*d9f75844SAndroid Build Coastguard Worker // Set the other contents to use the same ICE credentials.
466*d9f75844SAndroid Build Coastguard Worker const std::string& selected_ufrag =
467*d9f75844SAndroid Build Coastguard Worker selected_transport_info->description.ice_ufrag;
468*d9f75844SAndroid Build Coastguard Worker const std::string& selected_pwd =
469*d9f75844SAndroid Build Coastguard Worker selected_transport_info->description.ice_pwd;
470*d9f75844SAndroid Build Coastguard Worker ConnectionRole selected_connection_role =
471*d9f75844SAndroid Build Coastguard Worker selected_transport_info->description.connection_role;
472*d9f75844SAndroid Build Coastguard Worker for (TransportInfo& transport_info : sdesc->transport_infos()) {
473*d9f75844SAndroid Build Coastguard Worker if (bundle_group.HasContentName(transport_info.content_name) &&
474*d9f75844SAndroid Build Coastguard Worker transport_info.content_name != selected_content_name) {
475*d9f75844SAndroid Build Coastguard Worker transport_info.description.ice_ufrag = selected_ufrag;
476*d9f75844SAndroid Build Coastguard Worker transport_info.description.ice_pwd = selected_pwd;
477*d9f75844SAndroid Build Coastguard Worker transport_info.description.connection_role = selected_connection_role;
478*d9f75844SAndroid Build Coastguard Worker }
479*d9f75844SAndroid Build Coastguard Worker }
480*d9f75844SAndroid Build Coastguard Worker return true;
481*d9f75844SAndroid Build Coastguard Worker }
482*d9f75844SAndroid Build Coastguard Worker
483*d9f75844SAndroid Build Coastguard Worker // Gets the CryptoParamsVec of the given `content_name` from `sdesc`, and
484*d9f75844SAndroid Build Coastguard Worker // sets it to `cryptos`.
GetCryptosByName(const SessionDescription * sdesc,const std::string & content_name,CryptoParamsVec * cryptos)485*d9f75844SAndroid Build Coastguard Worker static bool GetCryptosByName(const SessionDescription* sdesc,
486*d9f75844SAndroid Build Coastguard Worker const std::string& content_name,
487*d9f75844SAndroid Build Coastguard Worker CryptoParamsVec* cryptos) {
488*d9f75844SAndroid Build Coastguard Worker if (!sdesc || !cryptos) {
489*d9f75844SAndroid Build Coastguard Worker return false;
490*d9f75844SAndroid Build Coastguard Worker }
491*d9f75844SAndroid Build Coastguard Worker const ContentInfo* content = sdesc->GetContentByName(content_name);
492*d9f75844SAndroid Build Coastguard Worker if (!content || !content->media_description()) {
493*d9f75844SAndroid Build Coastguard Worker return false;
494*d9f75844SAndroid Build Coastguard Worker }
495*d9f75844SAndroid Build Coastguard Worker *cryptos = content->media_description()->cryptos();
496*d9f75844SAndroid Build Coastguard Worker return true;
497*d9f75844SAndroid Build Coastguard Worker }
498*d9f75844SAndroid Build Coastguard Worker
499*d9f75844SAndroid Build Coastguard Worker // Prunes the `target_cryptos` by removing the crypto params (cipher_suite)
500*d9f75844SAndroid Build Coastguard Worker // which are not available in `filter`.
PruneCryptos(const CryptoParamsVec & filter,CryptoParamsVec * target_cryptos)501*d9f75844SAndroid Build Coastguard Worker static void PruneCryptos(const CryptoParamsVec& filter,
502*d9f75844SAndroid Build Coastguard Worker CryptoParamsVec* target_cryptos) {
503*d9f75844SAndroid Build Coastguard Worker if (!target_cryptos) {
504*d9f75844SAndroid Build Coastguard Worker return;
505*d9f75844SAndroid Build Coastguard Worker }
506*d9f75844SAndroid Build Coastguard Worker
507*d9f75844SAndroid Build Coastguard Worker target_cryptos->erase(
508*d9f75844SAndroid Build Coastguard Worker std::remove_if(target_cryptos->begin(), target_cryptos->end(),
509*d9f75844SAndroid Build Coastguard Worker // Returns true if the `crypto`'s cipher_suite is not
510*d9f75844SAndroid Build Coastguard Worker // found in `filter`.
511*d9f75844SAndroid Build Coastguard Worker [&filter](const CryptoParams& crypto) {
512*d9f75844SAndroid Build Coastguard Worker for (const CryptoParams& entry : filter) {
513*d9f75844SAndroid Build Coastguard Worker if (entry.cipher_suite == crypto.cipher_suite)
514*d9f75844SAndroid Build Coastguard Worker return false;
515*d9f75844SAndroid Build Coastguard Worker }
516*d9f75844SAndroid Build Coastguard Worker return true;
517*d9f75844SAndroid Build Coastguard Worker }),
518*d9f75844SAndroid Build Coastguard Worker target_cryptos->end());
519*d9f75844SAndroid Build Coastguard Worker }
520*d9f75844SAndroid Build Coastguard Worker
IsRtpContent(SessionDescription * sdesc,const std::string & content_name)521*d9f75844SAndroid Build Coastguard Worker static bool IsRtpContent(SessionDescription* sdesc,
522*d9f75844SAndroid Build Coastguard Worker const std::string& content_name) {
523*d9f75844SAndroid Build Coastguard Worker bool is_rtp = false;
524*d9f75844SAndroid Build Coastguard Worker ContentInfo* content = sdesc->GetContentByName(content_name);
525*d9f75844SAndroid Build Coastguard Worker if (content && content->media_description()) {
526*d9f75844SAndroid Build Coastguard Worker is_rtp = IsRtpProtocol(content->media_description()->protocol());
527*d9f75844SAndroid Build Coastguard Worker }
528*d9f75844SAndroid Build Coastguard Worker return is_rtp;
529*d9f75844SAndroid Build Coastguard Worker }
530*d9f75844SAndroid Build Coastguard Worker
531*d9f75844SAndroid Build Coastguard Worker // Updates the crypto parameters of the `sdesc` according to the given
532*d9f75844SAndroid Build Coastguard Worker // `bundle_group`. The crypto parameters of all the contents within the
533*d9f75844SAndroid Build Coastguard Worker // `bundle_group` should be updated to use the common subset of the
534*d9f75844SAndroid Build Coastguard Worker // available cryptos.
UpdateCryptoParamsForBundle(const ContentGroup & bundle_group,SessionDescription * sdesc)535*d9f75844SAndroid Build Coastguard Worker static bool UpdateCryptoParamsForBundle(const ContentGroup& bundle_group,
536*d9f75844SAndroid Build Coastguard Worker SessionDescription* sdesc) {
537*d9f75844SAndroid Build Coastguard Worker // The bundle should not be empty.
538*d9f75844SAndroid Build Coastguard Worker if (!sdesc || !bundle_group.FirstContentName()) {
539*d9f75844SAndroid Build Coastguard Worker return false;
540*d9f75844SAndroid Build Coastguard Worker }
541*d9f75844SAndroid Build Coastguard Worker
542*d9f75844SAndroid Build Coastguard Worker bool common_cryptos_needed = false;
543*d9f75844SAndroid Build Coastguard Worker // Get the common cryptos.
544*d9f75844SAndroid Build Coastguard Worker const ContentNames& content_names = bundle_group.content_names();
545*d9f75844SAndroid Build Coastguard Worker CryptoParamsVec common_cryptos;
546*d9f75844SAndroid Build Coastguard Worker bool first = true;
547*d9f75844SAndroid Build Coastguard Worker for (const std::string& content_name : content_names) {
548*d9f75844SAndroid Build Coastguard Worker if (!IsRtpContent(sdesc, content_name)) {
549*d9f75844SAndroid Build Coastguard Worker continue;
550*d9f75844SAndroid Build Coastguard Worker }
551*d9f75844SAndroid Build Coastguard Worker // The common cryptos are needed if any of the content does not have DTLS
552*d9f75844SAndroid Build Coastguard Worker // enabled.
553*d9f75844SAndroid Build Coastguard Worker if (!sdesc->GetTransportInfoByName(content_name)->description.secure()) {
554*d9f75844SAndroid Build Coastguard Worker common_cryptos_needed = true;
555*d9f75844SAndroid Build Coastguard Worker }
556*d9f75844SAndroid Build Coastguard Worker if (first) {
557*d9f75844SAndroid Build Coastguard Worker first = false;
558*d9f75844SAndroid Build Coastguard Worker // Initial the common_cryptos with the first content in the bundle group.
559*d9f75844SAndroid Build Coastguard Worker if (!GetCryptosByName(sdesc, content_name, &common_cryptos)) {
560*d9f75844SAndroid Build Coastguard Worker return false;
561*d9f75844SAndroid Build Coastguard Worker }
562*d9f75844SAndroid Build Coastguard Worker if (common_cryptos.empty()) {
563*d9f75844SAndroid Build Coastguard Worker // If there's no crypto params, we should just return.
564*d9f75844SAndroid Build Coastguard Worker return true;
565*d9f75844SAndroid Build Coastguard Worker }
566*d9f75844SAndroid Build Coastguard Worker } else {
567*d9f75844SAndroid Build Coastguard Worker CryptoParamsVec cryptos;
568*d9f75844SAndroid Build Coastguard Worker if (!GetCryptosByName(sdesc, content_name, &cryptos)) {
569*d9f75844SAndroid Build Coastguard Worker return false;
570*d9f75844SAndroid Build Coastguard Worker }
571*d9f75844SAndroid Build Coastguard Worker PruneCryptos(cryptos, &common_cryptos);
572*d9f75844SAndroid Build Coastguard Worker }
573*d9f75844SAndroid Build Coastguard Worker }
574*d9f75844SAndroid Build Coastguard Worker
575*d9f75844SAndroid Build Coastguard Worker if (common_cryptos.empty() && common_cryptos_needed) {
576*d9f75844SAndroid Build Coastguard Worker return false;
577*d9f75844SAndroid Build Coastguard Worker }
578*d9f75844SAndroid Build Coastguard Worker
579*d9f75844SAndroid Build Coastguard Worker // Update to use the common cryptos.
580*d9f75844SAndroid Build Coastguard Worker for (const std::string& content_name : content_names) {
581*d9f75844SAndroid Build Coastguard Worker if (!IsRtpContent(sdesc, content_name)) {
582*d9f75844SAndroid Build Coastguard Worker continue;
583*d9f75844SAndroid Build Coastguard Worker }
584*d9f75844SAndroid Build Coastguard Worker ContentInfo* content = sdesc->GetContentByName(content_name);
585*d9f75844SAndroid Build Coastguard Worker if (IsMediaContent(content)) {
586*d9f75844SAndroid Build Coastguard Worker MediaContentDescription* media_desc = content->media_description();
587*d9f75844SAndroid Build Coastguard Worker if (!media_desc) {
588*d9f75844SAndroid Build Coastguard Worker return false;
589*d9f75844SAndroid Build Coastguard Worker }
590*d9f75844SAndroid Build Coastguard Worker media_desc->set_cryptos(common_cryptos);
591*d9f75844SAndroid Build Coastguard Worker }
592*d9f75844SAndroid Build Coastguard Worker }
593*d9f75844SAndroid Build Coastguard Worker return true;
594*d9f75844SAndroid Build Coastguard Worker }
595*d9f75844SAndroid Build Coastguard Worker
GetActiveContents(const SessionDescription & description,const MediaSessionOptions & session_options)596*d9f75844SAndroid Build Coastguard Worker static std::vector<const ContentInfo*> GetActiveContents(
597*d9f75844SAndroid Build Coastguard Worker const SessionDescription& description,
598*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options) {
599*d9f75844SAndroid Build Coastguard Worker std::vector<const ContentInfo*> active_contents;
600*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < description.contents().size(); ++i) {
601*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LT(i, session_options.media_description_options.size());
602*d9f75844SAndroid Build Coastguard Worker const ContentInfo& content = description.contents()[i];
603*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_options =
604*d9f75844SAndroid Build Coastguard Worker session_options.media_description_options[i];
605*d9f75844SAndroid Build Coastguard Worker if (!content.rejected && !media_options.stopped &&
606*d9f75844SAndroid Build Coastguard Worker content.name == media_options.mid) {
607*d9f75844SAndroid Build Coastguard Worker active_contents.push_back(&content);
608*d9f75844SAndroid Build Coastguard Worker }
609*d9f75844SAndroid Build Coastguard Worker }
610*d9f75844SAndroid Build Coastguard Worker return active_contents;
611*d9f75844SAndroid Build Coastguard Worker }
612*d9f75844SAndroid Build Coastguard Worker
613*d9f75844SAndroid Build Coastguard Worker template <class C>
ContainsRtxCodec(const std::vector<C> & codecs)614*d9f75844SAndroid Build Coastguard Worker static bool ContainsRtxCodec(const std::vector<C>& codecs) {
615*d9f75844SAndroid Build Coastguard Worker for (const auto& codec : codecs) {
616*d9f75844SAndroid Build Coastguard Worker if (IsRtxCodec(codec)) {
617*d9f75844SAndroid Build Coastguard Worker return true;
618*d9f75844SAndroid Build Coastguard Worker }
619*d9f75844SAndroid Build Coastguard Worker }
620*d9f75844SAndroid Build Coastguard Worker return false;
621*d9f75844SAndroid Build Coastguard Worker }
622*d9f75844SAndroid Build Coastguard Worker
623*d9f75844SAndroid Build Coastguard Worker template <class C>
IsRedCodec(const C & codec)624*d9f75844SAndroid Build Coastguard Worker static bool IsRedCodec(const C& codec) {
625*d9f75844SAndroid Build Coastguard Worker return absl::EqualsIgnoreCase(codec.name, kRedCodecName);
626*d9f75844SAndroid Build Coastguard Worker }
627*d9f75844SAndroid Build Coastguard Worker
628*d9f75844SAndroid Build Coastguard Worker template <class C>
IsRtxCodec(const C & codec)629*d9f75844SAndroid Build Coastguard Worker static bool IsRtxCodec(const C& codec) {
630*d9f75844SAndroid Build Coastguard Worker return absl::EqualsIgnoreCase(codec.name, kRtxCodecName);
631*d9f75844SAndroid Build Coastguard Worker }
632*d9f75844SAndroid Build Coastguard Worker
633*d9f75844SAndroid Build Coastguard Worker template <class C>
ContainsFlexfecCodec(const std::vector<C> & codecs)634*d9f75844SAndroid Build Coastguard Worker static bool ContainsFlexfecCodec(const std::vector<C>& codecs) {
635*d9f75844SAndroid Build Coastguard Worker for (const auto& codec : codecs) {
636*d9f75844SAndroid Build Coastguard Worker if (IsFlexfecCodec(codec)) {
637*d9f75844SAndroid Build Coastguard Worker return true;
638*d9f75844SAndroid Build Coastguard Worker }
639*d9f75844SAndroid Build Coastguard Worker }
640*d9f75844SAndroid Build Coastguard Worker return false;
641*d9f75844SAndroid Build Coastguard Worker }
642*d9f75844SAndroid Build Coastguard Worker
643*d9f75844SAndroid Build Coastguard Worker template <class C>
IsFlexfecCodec(const C & codec)644*d9f75844SAndroid Build Coastguard Worker static bool IsFlexfecCodec(const C& codec) {
645*d9f75844SAndroid Build Coastguard Worker return absl::EqualsIgnoreCase(codec.name, kFlexfecCodecName);
646*d9f75844SAndroid Build Coastguard Worker }
647*d9f75844SAndroid Build Coastguard Worker
648*d9f75844SAndroid Build Coastguard Worker template <class C>
IsUlpfecCodec(const C & codec)649*d9f75844SAndroid Build Coastguard Worker static bool IsUlpfecCodec(const C& codec) {
650*d9f75844SAndroid Build Coastguard Worker return absl::EqualsIgnoreCase(codec.name, kUlpfecCodecName);
651*d9f75844SAndroid Build Coastguard Worker }
652*d9f75844SAndroid Build Coastguard Worker
653*d9f75844SAndroid Build Coastguard Worker template <class C>
IsComfortNoiseCodec(const C & codec)654*d9f75844SAndroid Build Coastguard Worker static bool IsComfortNoiseCodec(const C& codec) {
655*d9f75844SAndroid Build Coastguard Worker return absl::EqualsIgnoreCase(codec.name, kComfortNoiseCodecName);
656*d9f75844SAndroid Build Coastguard Worker }
657*d9f75844SAndroid Build Coastguard Worker
658*d9f75844SAndroid Build Coastguard Worker // Create a media content to be offered for the given `sender_options`,
659*d9f75844SAndroid Build Coastguard Worker // according to the given options.rtcp_mux, session_options.is_muc, codecs,
660*d9f75844SAndroid Build Coastguard Worker // secure_transport, crypto, and current_streams. If we don't currently have
661*d9f75844SAndroid Build Coastguard Worker // crypto (in current_cryptos) and it is enabled (in secure_policy), crypto is
662*d9f75844SAndroid Build Coastguard Worker // created (according to crypto_suites). The created content is added to the
663*d9f75844SAndroid Build Coastguard Worker // offer.
CreateContentOffer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const SecurePolicy & secure_policy,const CryptoParamsVec * current_cryptos,const std::vector<std::string> & crypto_suites,const RtpHeaderExtensions & rtp_extensions,UniqueRandomIdGenerator * ssrc_generator,StreamParamsVec * current_streams,MediaContentDescription * offer)664*d9f75844SAndroid Build Coastguard Worker static bool CreateContentOffer(
665*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
666*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
667*d9f75844SAndroid Build Coastguard Worker const SecurePolicy& secure_policy,
668*d9f75844SAndroid Build Coastguard Worker const CryptoParamsVec* current_cryptos,
669*d9f75844SAndroid Build Coastguard Worker const std::vector<std::string>& crypto_suites,
670*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& rtp_extensions,
671*d9f75844SAndroid Build Coastguard Worker UniqueRandomIdGenerator* ssrc_generator,
672*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
673*d9f75844SAndroid Build Coastguard Worker MediaContentDescription* offer) {
674*d9f75844SAndroid Build Coastguard Worker offer->set_rtcp_mux(session_options.rtcp_mux_enabled);
675*d9f75844SAndroid Build Coastguard Worker if (offer->type() == cricket::MEDIA_TYPE_VIDEO) {
676*d9f75844SAndroid Build Coastguard Worker offer->set_rtcp_reduced_size(true);
677*d9f75844SAndroid Build Coastguard Worker }
678*d9f75844SAndroid Build Coastguard Worker
679*d9f75844SAndroid Build Coastguard Worker // Build the vector of header extensions with directions for this
680*d9f75844SAndroid Build Coastguard Worker // media_description's options.
681*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions extensions;
682*d9f75844SAndroid Build Coastguard Worker for (auto extension_with_id : rtp_extensions) {
683*d9f75844SAndroid Build Coastguard Worker for (const auto& extension : media_description_options.header_extensions) {
684*d9f75844SAndroid Build Coastguard Worker if (extension_with_id.uri == extension.uri) {
685*d9f75844SAndroid Build Coastguard Worker // TODO(crbug.com/1051821): Configure the extension direction from
686*d9f75844SAndroid Build Coastguard Worker // the information in the media_description_options extension
687*d9f75844SAndroid Build Coastguard Worker // capability.
688*d9f75844SAndroid Build Coastguard Worker extensions.push_back(extension_with_id);
689*d9f75844SAndroid Build Coastguard Worker }
690*d9f75844SAndroid Build Coastguard Worker }
691*d9f75844SAndroid Build Coastguard Worker }
692*d9f75844SAndroid Build Coastguard Worker offer->set_rtp_header_extensions(extensions);
693*d9f75844SAndroid Build Coastguard Worker
694*d9f75844SAndroid Build Coastguard Worker AddSimulcastToMediaDescription(media_description_options, offer);
695*d9f75844SAndroid Build Coastguard Worker
696*d9f75844SAndroid Build Coastguard Worker if (secure_policy != SEC_DISABLED) {
697*d9f75844SAndroid Build Coastguard Worker if (current_cryptos) {
698*d9f75844SAndroid Build Coastguard Worker AddMediaCryptos(*current_cryptos, offer);
699*d9f75844SAndroid Build Coastguard Worker }
700*d9f75844SAndroid Build Coastguard Worker if (offer->cryptos().empty()) {
701*d9f75844SAndroid Build Coastguard Worker if (!CreateMediaCryptos(crypto_suites, offer)) {
702*d9f75844SAndroid Build Coastguard Worker return false;
703*d9f75844SAndroid Build Coastguard Worker }
704*d9f75844SAndroid Build Coastguard Worker }
705*d9f75844SAndroid Build Coastguard Worker }
706*d9f75844SAndroid Build Coastguard Worker
707*d9f75844SAndroid Build Coastguard Worker if (secure_policy == SEC_REQUIRED && offer->cryptos().empty()) {
708*d9f75844SAndroid Build Coastguard Worker return false;
709*d9f75844SAndroid Build Coastguard Worker }
710*d9f75844SAndroid Build Coastguard Worker return true;
711*d9f75844SAndroid Build Coastguard Worker }
712*d9f75844SAndroid Build Coastguard Worker template <class C>
CreateMediaContentOffer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const std::vector<C> & codecs,const SecurePolicy & secure_policy,const CryptoParamsVec * current_cryptos,const std::vector<std::string> & crypto_suites,const RtpHeaderExtensions & rtp_extensions,UniqueRandomIdGenerator * ssrc_generator,StreamParamsVec * current_streams,MediaContentDescriptionImpl<C> * offer,const webrtc::FieldTrialsView & field_trials)713*d9f75844SAndroid Build Coastguard Worker static bool CreateMediaContentOffer(
714*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
715*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
716*d9f75844SAndroid Build Coastguard Worker const std::vector<C>& codecs,
717*d9f75844SAndroid Build Coastguard Worker const SecurePolicy& secure_policy,
718*d9f75844SAndroid Build Coastguard Worker const CryptoParamsVec* current_cryptos,
719*d9f75844SAndroid Build Coastguard Worker const std::vector<std::string>& crypto_suites,
720*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& rtp_extensions,
721*d9f75844SAndroid Build Coastguard Worker UniqueRandomIdGenerator* ssrc_generator,
722*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
723*d9f75844SAndroid Build Coastguard Worker MediaContentDescriptionImpl<C>* offer,
724*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView& field_trials) {
725*d9f75844SAndroid Build Coastguard Worker offer->AddCodecs(codecs);
726*d9f75844SAndroid Build Coastguard Worker if (!AddStreamParams(media_description_options.sender_options,
727*d9f75844SAndroid Build Coastguard Worker session_options.rtcp_cname, ssrc_generator,
728*d9f75844SAndroid Build Coastguard Worker current_streams, offer, field_trials)) {
729*d9f75844SAndroid Build Coastguard Worker return false;
730*d9f75844SAndroid Build Coastguard Worker }
731*d9f75844SAndroid Build Coastguard Worker
732*d9f75844SAndroid Build Coastguard Worker return CreateContentOffer(media_description_options, session_options,
733*d9f75844SAndroid Build Coastguard Worker secure_policy, current_cryptos, crypto_suites,
734*d9f75844SAndroid Build Coastguard Worker rtp_extensions, ssrc_generator, current_streams,
735*d9f75844SAndroid Build Coastguard Worker offer);
736*d9f75844SAndroid Build Coastguard Worker }
737*d9f75844SAndroid Build Coastguard Worker
738*d9f75844SAndroid Build Coastguard Worker template <class C>
ReferencedCodecsMatch(const std::vector<C> & codecs1,const int codec1_id,const std::vector<C> & codecs2,const int codec2_id,const webrtc::FieldTrialsView * field_trials)739*d9f75844SAndroid Build Coastguard Worker static bool ReferencedCodecsMatch(const std::vector<C>& codecs1,
740*d9f75844SAndroid Build Coastguard Worker const int codec1_id,
741*d9f75844SAndroid Build Coastguard Worker const std::vector<C>& codecs2,
742*d9f75844SAndroid Build Coastguard Worker const int codec2_id,
743*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials) {
744*d9f75844SAndroid Build Coastguard Worker const C* codec1 = FindCodecById(codecs1, codec1_id);
745*d9f75844SAndroid Build Coastguard Worker const C* codec2 = FindCodecById(codecs2, codec2_id);
746*d9f75844SAndroid Build Coastguard Worker return codec1 != nullptr && codec2 != nullptr &&
747*d9f75844SAndroid Build Coastguard Worker codec1->Matches(*codec2, field_trials);
748*d9f75844SAndroid Build Coastguard Worker }
749*d9f75844SAndroid Build Coastguard Worker
750*d9f75844SAndroid Build Coastguard Worker template <class C>
NegotiatePacketization(const C & local_codec,const C & remote_codec,C * negotiated_codec)751*d9f75844SAndroid Build Coastguard Worker static void NegotiatePacketization(const C& local_codec,
752*d9f75844SAndroid Build Coastguard Worker const C& remote_codec,
753*d9f75844SAndroid Build Coastguard Worker C* negotiated_codec) {}
754*d9f75844SAndroid Build Coastguard Worker
755*d9f75844SAndroid Build Coastguard Worker template <>
NegotiatePacketization(const VideoCodec & local_codec,const VideoCodec & remote_codec,VideoCodec * negotiated_codec)756*d9f75844SAndroid Build Coastguard Worker void NegotiatePacketization(const VideoCodec& local_codec,
757*d9f75844SAndroid Build Coastguard Worker const VideoCodec& remote_codec,
758*d9f75844SAndroid Build Coastguard Worker VideoCodec* negotiated_codec) {
759*d9f75844SAndroid Build Coastguard Worker negotiated_codec->packetization =
760*d9f75844SAndroid Build Coastguard Worker VideoCodec::IntersectPacketization(local_codec, remote_codec);
761*d9f75844SAndroid Build Coastguard Worker }
762*d9f75844SAndroid Build Coastguard Worker
763*d9f75844SAndroid Build Coastguard Worker template <class C>
NegotiateCodecs(const std::vector<C> & local_codecs,const std::vector<C> & offered_codecs,std::vector<C> * negotiated_codecs,bool keep_offer_order,const webrtc::FieldTrialsView * field_trials)764*d9f75844SAndroid Build Coastguard Worker static void NegotiateCodecs(const std::vector<C>& local_codecs,
765*d9f75844SAndroid Build Coastguard Worker const std::vector<C>& offered_codecs,
766*d9f75844SAndroid Build Coastguard Worker std::vector<C>* negotiated_codecs,
767*d9f75844SAndroid Build Coastguard Worker bool keep_offer_order,
768*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials) {
769*d9f75844SAndroid Build Coastguard Worker for (const C& ours : local_codecs) {
770*d9f75844SAndroid Build Coastguard Worker C theirs;
771*d9f75844SAndroid Build Coastguard Worker // Note that we intentionally only find one matching codec for each of our
772*d9f75844SAndroid Build Coastguard Worker // local codecs, in case the remote offer contains duplicate codecs.
773*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec(local_codecs, offered_codecs, ours, &theirs,
774*d9f75844SAndroid Build Coastguard Worker field_trials)) {
775*d9f75844SAndroid Build Coastguard Worker C negotiated = ours;
776*d9f75844SAndroid Build Coastguard Worker NegotiatePacketization(ours, theirs, &negotiated);
777*d9f75844SAndroid Build Coastguard Worker negotiated.IntersectFeedbackParams(theirs);
778*d9f75844SAndroid Build Coastguard Worker if (IsRtxCodec(negotiated)) {
779*d9f75844SAndroid Build Coastguard Worker const auto apt_it =
780*d9f75844SAndroid Build Coastguard Worker theirs.params.find(kCodecParamAssociatedPayloadType);
781*d9f75844SAndroid Build Coastguard Worker // FindMatchingCodec shouldn't return something with no apt value.
782*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(apt_it != theirs.params.end());
783*d9f75844SAndroid Build Coastguard Worker negotiated.SetParam(kCodecParamAssociatedPayloadType, apt_it->second);
784*d9f75844SAndroid Build Coastguard Worker
785*d9f75844SAndroid Build Coastguard Worker // We support parsing the declarative rtx-time parameter.
786*d9f75844SAndroid Build Coastguard Worker const auto rtx_time_it = theirs.params.find(kCodecParamRtxTime);
787*d9f75844SAndroid Build Coastguard Worker if (rtx_time_it != theirs.params.end()) {
788*d9f75844SAndroid Build Coastguard Worker negotiated.SetParam(kCodecParamRtxTime, rtx_time_it->second);
789*d9f75844SAndroid Build Coastguard Worker }
790*d9f75844SAndroid Build Coastguard Worker } else if (IsRedCodec(negotiated)) {
791*d9f75844SAndroid Build Coastguard Worker const auto red_it = theirs.params.find(kCodecParamNotInNameValueFormat);
792*d9f75844SAndroid Build Coastguard Worker if (red_it != theirs.params.end()) {
793*d9f75844SAndroid Build Coastguard Worker negotiated.SetParam(kCodecParamNotInNameValueFormat, red_it->second);
794*d9f75844SAndroid Build Coastguard Worker }
795*d9f75844SAndroid Build Coastguard Worker }
796*d9f75844SAndroid Build Coastguard Worker if (absl::EqualsIgnoreCase(ours.name, kH264CodecName)) {
797*d9f75844SAndroid Build Coastguard Worker webrtc::H264GenerateProfileLevelIdForAnswer(ours.params, theirs.params,
798*d9f75844SAndroid Build Coastguard Worker &negotiated.params);
799*d9f75844SAndroid Build Coastguard Worker }
800*d9f75844SAndroid Build Coastguard Worker negotiated.id = theirs.id;
801*d9f75844SAndroid Build Coastguard Worker negotiated.name = theirs.name;
802*d9f75844SAndroid Build Coastguard Worker negotiated_codecs->push_back(std::move(negotiated));
803*d9f75844SAndroid Build Coastguard Worker }
804*d9f75844SAndroid Build Coastguard Worker }
805*d9f75844SAndroid Build Coastguard Worker if (keep_offer_order) {
806*d9f75844SAndroid Build Coastguard Worker // RFC3264: Although the answerer MAY list the formats in their desired
807*d9f75844SAndroid Build Coastguard Worker // order of preference, it is RECOMMENDED that unless there is a
808*d9f75844SAndroid Build Coastguard Worker // specific reason, the answerer list formats in the same relative order
809*d9f75844SAndroid Build Coastguard Worker // they were present in the offer.
810*d9f75844SAndroid Build Coastguard Worker // This can be skipped when the transceiver has any codec preferences.
811*d9f75844SAndroid Build Coastguard Worker std::unordered_map<int, int> payload_type_preferences;
812*d9f75844SAndroid Build Coastguard Worker int preference = static_cast<int>(offered_codecs.size() + 1);
813*d9f75844SAndroid Build Coastguard Worker for (const C& codec : offered_codecs) {
814*d9f75844SAndroid Build Coastguard Worker payload_type_preferences[codec.id] = preference--;
815*d9f75844SAndroid Build Coastguard Worker }
816*d9f75844SAndroid Build Coastguard Worker absl::c_sort(*negotiated_codecs, [&payload_type_preferences](const C& a,
817*d9f75844SAndroid Build Coastguard Worker const C& b) {
818*d9f75844SAndroid Build Coastguard Worker return payload_type_preferences[a.id] > payload_type_preferences[b.id];
819*d9f75844SAndroid Build Coastguard Worker });
820*d9f75844SAndroid Build Coastguard Worker }
821*d9f75844SAndroid Build Coastguard Worker }
822*d9f75844SAndroid Build Coastguard Worker
823*d9f75844SAndroid Build Coastguard Worker // Finds a codec in `codecs2` that matches `codec_to_match`, which is
824*d9f75844SAndroid Build Coastguard Worker // a member of `codecs1`. If `codec_to_match` is an RED or RTX codec, both
825*d9f75844SAndroid Build Coastguard Worker // the codecs themselves and their associated codecs must match.
826*d9f75844SAndroid Build Coastguard Worker template <class C>
FindMatchingCodec(const std::vector<C> & codecs1,const std::vector<C> & codecs2,const C & codec_to_match,C * found_codec,const webrtc::FieldTrialsView * field_trials)827*d9f75844SAndroid Build Coastguard Worker static bool FindMatchingCodec(const std::vector<C>& codecs1,
828*d9f75844SAndroid Build Coastguard Worker const std::vector<C>& codecs2,
829*d9f75844SAndroid Build Coastguard Worker const C& codec_to_match,
830*d9f75844SAndroid Build Coastguard Worker C* found_codec,
831*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials) {
832*d9f75844SAndroid Build Coastguard Worker // `codec_to_match` should be a member of `codecs1`, in order to look up
833*d9f75844SAndroid Build Coastguard Worker // RED/RTX codecs' associated codecs correctly. If not, that's a programming
834*d9f75844SAndroid Build Coastguard Worker // error.
835*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(absl::c_any_of(codecs1, [&codec_to_match](const C& codec) {
836*d9f75844SAndroid Build Coastguard Worker return &codec == &codec_to_match;
837*d9f75844SAndroid Build Coastguard Worker }));
838*d9f75844SAndroid Build Coastguard Worker for (const C& potential_match : codecs2) {
839*d9f75844SAndroid Build Coastguard Worker if (potential_match.Matches(codec_to_match, field_trials)) {
840*d9f75844SAndroid Build Coastguard Worker if (IsRtxCodec(codec_to_match)) {
841*d9f75844SAndroid Build Coastguard Worker int apt_value_1 = 0;
842*d9f75844SAndroid Build Coastguard Worker int apt_value_2 = 0;
843*d9f75844SAndroid Build Coastguard Worker if (!codec_to_match.GetParam(kCodecParamAssociatedPayloadType,
844*d9f75844SAndroid Build Coastguard Worker &apt_value_1) ||
845*d9f75844SAndroid Build Coastguard Worker !potential_match.GetParam(kCodecParamAssociatedPayloadType,
846*d9f75844SAndroid Build Coastguard Worker &apt_value_2)) {
847*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "RTX missing associated payload type.";
848*d9f75844SAndroid Build Coastguard Worker continue;
849*d9f75844SAndroid Build Coastguard Worker }
850*d9f75844SAndroid Build Coastguard Worker if (!ReferencedCodecsMatch(codecs1, apt_value_1, codecs2, apt_value_2,
851*d9f75844SAndroid Build Coastguard Worker field_trials)) {
852*d9f75844SAndroid Build Coastguard Worker continue;
853*d9f75844SAndroid Build Coastguard Worker }
854*d9f75844SAndroid Build Coastguard Worker } else if (IsRedCodec(codec_to_match)) {
855*d9f75844SAndroid Build Coastguard Worker auto red_parameters_1 =
856*d9f75844SAndroid Build Coastguard Worker codec_to_match.params.find(kCodecParamNotInNameValueFormat);
857*d9f75844SAndroid Build Coastguard Worker auto red_parameters_2 =
858*d9f75844SAndroid Build Coastguard Worker potential_match.params.find(kCodecParamNotInNameValueFormat);
859*d9f75844SAndroid Build Coastguard Worker bool has_parameters_1 = red_parameters_1 != codec_to_match.params.end();
860*d9f75844SAndroid Build Coastguard Worker bool has_parameters_2 =
861*d9f75844SAndroid Build Coastguard Worker red_parameters_2 != potential_match.params.end();
862*d9f75844SAndroid Build Coastguard Worker if (has_parameters_1 && has_parameters_2) {
863*d9f75844SAndroid Build Coastguard Worker // Mixed reference codecs (i.e. 111/112) are not supported.
864*d9f75844SAndroid Build Coastguard Worker // Different levels of redundancy between offer and answer are
865*d9f75844SAndroid Build Coastguard Worker // since RED is considered to be declarative.
866*d9f75844SAndroid Build Coastguard Worker std::vector<absl::string_view> redundant_payloads_1 =
867*d9f75844SAndroid Build Coastguard Worker rtc::split(red_parameters_1->second, '/');
868*d9f75844SAndroid Build Coastguard Worker std::vector<absl::string_view> redundant_payloads_2 =
869*d9f75844SAndroid Build Coastguard Worker rtc::split(red_parameters_2->second, '/');
870*d9f75844SAndroid Build Coastguard Worker if (redundant_payloads_1.size() > 0 &&
871*d9f75844SAndroid Build Coastguard Worker redundant_payloads_2.size() > 0) {
872*d9f75844SAndroid Build Coastguard Worker bool consistent = true;
873*d9f75844SAndroid Build Coastguard Worker for (size_t i = 1; i < redundant_payloads_1.size(); i++) {
874*d9f75844SAndroid Build Coastguard Worker if (redundant_payloads_1[i] != redundant_payloads_1[0]) {
875*d9f75844SAndroid Build Coastguard Worker consistent = false;
876*d9f75844SAndroid Build Coastguard Worker break;
877*d9f75844SAndroid Build Coastguard Worker }
878*d9f75844SAndroid Build Coastguard Worker }
879*d9f75844SAndroid Build Coastguard Worker for (size_t i = 1; i < redundant_payloads_2.size(); i++) {
880*d9f75844SAndroid Build Coastguard Worker if (redundant_payloads_2[i] != redundant_payloads_2[0]) {
881*d9f75844SAndroid Build Coastguard Worker consistent = false;
882*d9f75844SAndroid Build Coastguard Worker break;
883*d9f75844SAndroid Build Coastguard Worker }
884*d9f75844SAndroid Build Coastguard Worker }
885*d9f75844SAndroid Build Coastguard Worker if (!consistent) {
886*d9f75844SAndroid Build Coastguard Worker continue;
887*d9f75844SAndroid Build Coastguard Worker }
888*d9f75844SAndroid Build Coastguard Worker
889*d9f75844SAndroid Build Coastguard Worker int red_value_1;
890*d9f75844SAndroid Build Coastguard Worker int red_value_2;
891*d9f75844SAndroid Build Coastguard Worker if (rtc::FromString(redundant_payloads_1[0], &red_value_1) &&
892*d9f75844SAndroid Build Coastguard Worker rtc::FromString(redundant_payloads_2[0], &red_value_2)) {
893*d9f75844SAndroid Build Coastguard Worker if (!ReferencedCodecsMatch(codecs1, red_value_1, codecs2,
894*d9f75844SAndroid Build Coastguard Worker red_value_2, field_trials)) {
895*d9f75844SAndroid Build Coastguard Worker continue;
896*d9f75844SAndroid Build Coastguard Worker }
897*d9f75844SAndroid Build Coastguard Worker }
898*d9f75844SAndroid Build Coastguard Worker }
899*d9f75844SAndroid Build Coastguard Worker } else if (has_parameters_1 != has_parameters_2) {
900*d9f75844SAndroid Build Coastguard Worker continue;
901*d9f75844SAndroid Build Coastguard Worker }
902*d9f75844SAndroid Build Coastguard Worker }
903*d9f75844SAndroid Build Coastguard Worker if (found_codec) {
904*d9f75844SAndroid Build Coastguard Worker *found_codec = potential_match;
905*d9f75844SAndroid Build Coastguard Worker }
906*d9f75844SAndroid Build Coastguard Worker return true;
907*d9f75844SAndroid Build Coastguard Worker }
908*d9f75844SAndroid Build Coastguard Worker }
909*d9f75844SAndroid Build Coastguard Worker return false;
910*d9f75844SAndroid Build Coastguard Worker }
911*d9f75844SAndroid Build Coastguard Worker
912*d9f75844SAndroid Build Coastguard Worker // Find the codec in `codec_list` that `rtx_codec` is associated with.
913*d9f75844SAndroid Build Coastguard Worker template <class C>
GetAssociatedCodecForRtx(const std::vector<C> & codec_list,const C & rtx_codec)914*d9f75844SAndroid Build Coastguard Worker static const C* GetAssociatedCodecForRtx(const std::vector<C>& codec_list,
915*d9f75844SAndroid Build Coastguard Worker const C& rtx_codec) {
916*d9f75844SAndroid Build Coastguard Worker std::string associated_pt_str;
917*d9f75844SAndroid Build Coastguard Worker if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
918*d9f75844SAndroid Build Coastguard Worker &associated_pt_str)) {
919*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "RTX codec " << rtx_codec.name
920*d9f75844SAndroid Build Coastguard Worker << " is missing an associated payload type.";
921*d9f75844SAndroid Build Coastguard Worker return nullptr;
922*d9f75844SAndroid Build Coastguard Worker }
923*d9f75844SAndroid Build Coastguard Worker
924*d9f75844SAndroid Build Coastguard Worker int associated_pt;
925*d9f75844SAndroid Build Coastguard Worker if (!rtc::FromString(associated_pt_str, &associated_pt)) {
926*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str
927*d9f75844SAndroid Build Coastguard Worker << " of RTX codec " << rtx_codec.name
928*d9f75844SAndroid Build Coastguard Worker << " to an integer.";
929*d9f75844SAndroid Build Coastguard Worker return nullptr;
930*d9f75844SAndroid Build Coastguard Worker }
931*d9f75844SAndroid Build Coastguard Worker
932*d9f75844SAndroid Build Coastguard Worker // Find the associated codec for the RTX codec.
933*d9f75844SAndroid Build Coastguard Worker const C* associated_codec = FindCodecById(codec_list, associated_pt);
934*d9f75844SAndroid Build Coastguard Worker if (!associated_codec) {
935*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
936*d9f75844SAndroid Build Coastguard Worker << associated_pt << " for RTX codec " << rtx_codec.name
937*d9f75844SAndroid Build Coastguard Worker << ".";
938*d9f75844SAndroid Build Coastguard Worker }
939*d9f75844SAndroid Build Coastguard Worker return associated_codec;
940*d9f75844SAndroid Build Coastguard Worker }
941*d9f75844SAndroid Build Coastguard Worker
942*d9f75844SAndroid Build Coastguard Worker // Find the codec in `codec_list` that `red_codec` is associated with.
943*d9f75844SAndroid Build Coastguard Worker template <class C>
GetAssociatedCodecForRed(const std::vector<C> & codec_list,const C & red_codec)944*d9f75844SAndroid Build Coastguard Worker static const C* GetAssociatedCodecForRed(const std::vector<C>& codec_list,
945*d9f75844SAndroid Build Coastguard Worker const C& red_codec) {
946*d9f75844SAndroid Build Coastguard Worker std::string fmtp;
947*d9f75844SAndroid Build Coastguard Worker if (!red_codec.GetParam(kCodecParamNotInNameValueFormat, &fmtp)) {
948*d9f75844SAndroid Build Coastguard Worker // Normal for video/RED.
949*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "RED codec " << red_codec.name
950*d9f75844SAndroid Build Coastguard Worker << " is missing an associated payload type.";
951*d9f75844SAndroid Build Coastguard Worker return nullptr;
952*d9f75844SAndroid Build Coastguard Worker }
953*d9f75844SAndroid Build Coastguard Worker
954*d9f75844SAndroid Build Coastguard Worker std::vector<absl::string_view> redundant_payloads = rtc::split(fmtp, '/');
955*d9f75844SAndroid Build Coastguard Worker if (redundant_payloads.size() < 2) {
956*d9f75844SAndroid Build Coastguard Worker return nullptr;
957*d9f75844SAndroid Build Coastguard Worker }
958*d9f75844SAndroid Build Coastguard Worker
959*d9f75844SAndroid Build Coastguard Worker absl::string_view associated_pt_str = redundant_payloads[0];
960*d9f75844SAndroid Build Coastguard Worker int associated_pt;
961*d9f75844SAndroid Build Coastguard Worker if (!rtc::FromString(associated_pt_str, &associated_pt)) {
962*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Couldn't convert first payload type "
963*d9f75844SAndroid Build Coastguard Worker << associated_pt_str << " of RED codec "
964*d9f75844SAndroid Build Coastguard Worker << red_codec.name << " to an integer.";
965*d9f75844SAndroid Build Coastguard Worker return nullptr;
966*d9f75844SAndroid Build Coastguard Worker }
967*d9f75844SAndroid Build Coastguard Worker
968*d9f75844SAndroid Build Coastguard Worker // Find the associated codec for the RED codec.
969*d9f75844SAndroid Build Coastguard Worker const C* associated_codec = FindCodecById(codec_list, associated_pt);
970*d9f75844SAndroid Build Coastguard Worker if (!associated_codec) {
971*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
972*d9f75844SAndroid Build Coastguard Worker << associated_pt << " for RED codec " << red_codec.name
973*d9f75844SAndroid Build Coastguard Worker << ".";
974*d9f75844SAndroid Build Coastguard Worker }
975*d9f75844SAndroid Build Coastguard Worker return associated_codec;
976*d9f75844SAndroid Build Coastguard Worker }
977*d9f75844SAndroid Build Coastguard Worker
978*d9f75844SAndroid Build Coastguard Worker // Adds all codecs from `reference_codecs` to `offered_codecs` that don't
979*d9f75844SAndroid Build Coastguard Worker // already exist in `offered_codecs` and ensure the payload types don't
980*d9f75844SAndroid Build Coastguard Worker // collide.
981*d9f75844SAndroid Build Coastguard Worker template <class C>
MergeCodecs(const std::vector<C> & reference_codecs,std::vector<C> * offered_codecs,UsedPayloadTypes * used_pltypes,const webrtc::FieldTrialsView * field_trials)982*d9f75844SAndroid Build Coastguard Worker static void MergeCodecs(const std::vector<C>& reference_codecs,
983*d9f75844SAndroid Build Coastguard Worker std::vector<C>* offered_codecs,
984*d9f75844SAndroid Build Coastguard Worker UsedPayloadTypes* used_pltypes,
985*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials) {
986*d9f75844SAndroid Build Coastguard Worker // Add all new codecs that are not RTX/RED codecs.
987*d9f75844SAndroid Build Coastguard Worker // The two-pass splitting of the loops means preferring payload types
988*d9f75844SAndroid Build Coastguard Worker // of actual codecs with respect to collisions.
989*d9f75844SAndroid Build Coastguard Worker for (const C& reference_codec : reference_codecs) {
990*d9f75844SAndroid Build Coastguard Worker if (!IsRtxCodec(reference_codec) && !IsRedCodec(reference_codec) &&
991*d9f75844SAndroid Build Coastguard Worker !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
992*d9f75844SAndroid Build Coastguard Worker reference_codec, nullptr, field_trials)) {
993*d9f75844SAndroid Build Coastguard Worker C codec = reference_codec;
994*d9f75844SAndroid Build Coastguard Worker used_pltypes->FindAndSetIdUsed(&codec);
995*d9f75844SAndroid Build Coastguard Worker offered_codecs->push_back(codec);
996*d9f75844SAndroid Build Coastguard Worker }
997*d9f75844SAndroid Build Coastguard Worker }
998*d9f75844SAndroid Build Coastguard Worker
999*d9f75844SAndroid Build Coastguard Worker // Add all new RTX or RED codecs.
1000*d9f75844SAndroid Build Coastguard Worker for (const C& reference_codec : reference_codecs) {
1001*d9f75844SAndroid Build Coastguard Worker if (IsRtxCodec(reference_codec) &&
1002*d9f75844SAndroid Build Coastguard Worker !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
1003*d9f75844SAndroid Build Coastguard Worker reference_codec, nullptr, field_trials)) {
1004*d9f75844SAndroid Build Coastguard Worker C rtx_codec = reference_codec;
1005*d9f75844SAndroid Build Coastguard Worker const C* associated_codec =
1006*d9f75844SAndroid Build Coastguard Worker GetAssociatedCodecForRtx(reference_codecs, rtx_codec);
1007*d9f75844SAndroid Build Coastguard Worker if (!associated_codec) {
1008*d9f75844SAndroid Build Coastguard Worker continue;
1009*d9f75844SAndroid Build Coastguard Worker }
1010*d9f75844SAndroid Build Coastguard Worker // Find a codec in the offered list that matches the reference codec.
1011*d9f75844SAndroid Build Coastguard Worker // Its payload type may be different than the reference codec.
1012*d9f75844SAndroid Build Coastguard Worker C matching_codec;
1013*d9f75844SAndroid Build Coastguard Worker if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs,
1014*d9f75844SAndroid Build Coastguard Worker *associated_codec, &matching_codec,
1015*d9f75844SAndroid Build Coastguard Worker field_trials)) {
1016*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING)
1017*d9f75844SAndroid Build Coastguard Worker << "Couldn't find matching " << associated_codec->name << " codec.";
1018*d9f75844SAndroid Build Coastguard Worker continue;
1019*d9f75844SAndroid Build Coastguard Worker }
1020*d9f75844SAndroid Build Coastguard Worker
1021*d9f75844SAndroid Build Coastguard Worker rtx_codec.params[kCodecParamAssociatedPayloadType] =
1022*d9f75844SAndroid Build Coastguard Worker rtc::ToString(matching_codec.id);
1023*d9f75844SAndroid Build Coastguard Worker used_pltypes->FindAndSetIdUsed(&rtx_codec);
1024*d9f75844SAndroid Build Coastguard Worker offered_codecs->push_back(rtx_codec);
1025*d9f75844SAndroid Build Coastguard Worker } else if (IsRedCodec(reference_codec) &&
1026*d9f75844SAndroid Build Coastguard Worker !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
1027*d9f75844SAndroid Build Coastguard Worker reference_codec, nullptr, field_trials)) {
1028*d9f75844SAndroid Build Coastguard Worker C red_codec = reference_codec;
1029*d9f75844SAndroid Build Coastguard Worker const C* associated_codec =
1030*d9f75844SAndroid Build Coastguard Worker GetAssociatedCodecForRed(reference_codecs, red_codec);
1031*d9f75844SAndroid Build Coastguard Worker if (associated_codec) {
1032*d9f75844SAndroid Build Coastguard Worker C matching_codec;
1033*d9f75844SAndroid Build Coastguard Worker if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs,
1034*d9f75844SAndroid Build Coastguard Worker *associated_codec, &matching_codec,
1035*d9f75844SAndroid Build Coastguard Worker field_trials)) {
1036*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_WARNING) << "Couldn't find matching "
1037*d9f75844SAndroid Build Coastguard Worker << associated_codec->name << " codec.";
1038*d9f75844SAndroid Build Coastguard Worker continue;
1039*d9f75844SAndroid Build Coastguard Worker }
1040*d9f75844SAndroid Build Coastguard Worker
1041*d9f75844SAndroid Build Coastguard Worker red_codec.params[kCodecParamNotInNameValueFormat] =
1042*d9f75844SAndroid Build Coastguard Worker rtc::ToString(matching_codec.id) + "/" +
1043*d9f75844SAndroid Build Coastguard Worker rtc::ToString(matching_codec.id);
1044*d9f75844SAndroid Build Coastguard Worker }
1045*d9f75844SAndroid Build Coastguard Worker used_pltypes->FindAndSetIdUsed(&red_codec);
1046*d9f75844SAndroid Build Coastguard Worker offered_codecs->push_back(red_codec);
1047*d9f75844SAndroid Build Coastguard Worker }
1048*d9f75844SAndroid Build Coastguard Worker }
1049*d9f75844SAndroid Build Coastguard Worker }
1050*d9f75844SAndroid Build Coastguard Worker
1051*d9f75844SAndroid Build Coastguard Worker // `codecs` is a full list of codecs with correct payload type mappings, which
1052*d9f75844SAndroid Build Coastguard Worker // don't conflict with mappings of the other media type; `supported_codecs` is
1053*d9f75844SAndroid Build Coastguard Worker // a list filtered for the media section`s direction but with default payload
1054*d9f75844SAndroid Build Coastguard Worker // types.
1055*d9f75844SAndroid Build Coastguard Worker template <typename Codecs>
MatchCodecPreference(const std::vector<webrtc::RtpCodecCapability> & codec_preferences,const Codecs & codecs,const Codecs & supported_codecs,const webrtc::FieldTrialsView * field_trials)1056*d9f75844SAndroid Build Coastguard Worker static Codecs MatchCodecPreference(
1057*d9f75844SAndroid Build Coastguard Worker const std::vector<webrtc::RtpCodecCapability>& codec_preferences,
1058*d9f75844SAndroid Build Coastguard Worker const Codecs& codecs,
1059*d9f75844SAndroid Build Coastguard Worker const Codecs& supported_codecs,
1060*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials) {
1061*d9f75844SAndroid Build Coastguard Worker Codecs filtered_codecs;
1062*d9f75844SAndroid Build Coastguard Worker bool want_rtx = false;
1063*d9f75844SAndroid Build Coastguard Worker bool want_red = false;
1064*d9f75844SAndroid Build Coastguard Worker
1065*d9f75844SAndroid Build Coastguard Worker for (const auto& codec_preference : codec_preferences) {
1066*d9f75844SAndroid Build Coastguard Worker if (IsRtxCodec(codec_preference)) {
1067*d9f75844SAndroid Build Coastguard Worker want_rtx = true;
1068*d9f75844SAndroid Build Coastguard Worker } else if (IsRedCodec(codec_preference)) {
1069*d9f75844SAndroid Build Coastguard Worker want_red = true;
1070*d9f75844SAndroid Build Coastguard Worker }
1071*d9f75844SAndroid Build Coastguard Worker }
1072*d9f75844SAndroid Build Coastguard Worker for (const auto& codec_preference : codec_preferences) {
1073*d9f75844SAndroid Build Coastguard Worker auto found_codec = absl::c_find_if(
1074*d9f75844SAndroid Build Coastguard Worker supported_codecs,
1075*d9f75844SAndroid Build Coastguard Worker [&codec_preference](const typename Codecs::value_type& codec) {
1076*d9f75844SAndroid Build Coastguard Worker webrtc::RtpCodecParameters codec_parameters =
1077*d9f75844SAndroid Build Coastguard Worker codec.ToCodecParameters();
1078*d9f75844SAndroid Build Coastguard Worker return codec_parameters.name == codec_preference.name &&
1079*d9f75844SAndroid Build Coastguard Worker codec_parameters.kind == codec_preference.kind &&
1080*d9f75844SAndroid Build Coastguard Worker codec_parameters.num_channels ==
1081*d9f75844SAndroid Build Coastguard Worker codec_preference.num_channels &&
1082*d9f75844SAndroid Build Coastguard Worker codec_parameters.clock_rate == codec_preference.clock_rate &&
1083*d9f75844SAndroid Build Coastguard Worker codec_parameters.parameters == codec_preference.parameters;
1084*d9f75844SAndroid Build Coastguard Worker });
1085*d9f75844SAndroid Build Coastguard Worker
1086*d9f75844SAndroid Build Coastguard Worker if (found_codec != supported_codecs.end()) {
1087*d9f75844SAndroid Build Coastguard Worker typename Codecs::value_type found_codec_with_correct_pt;
1088*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec(supported_codecs, codecs, *found_codec,
1089*d9f75844SAndroid Build Coastguard Worker &found_codec_with_correct_pt, field_trials)) {
1090*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(found_codec_with_correct_pt);
1091*d9f75844SAndroid Build Coastguard Worker std::string id = rtc::ToString(found_codec_with_correct_pt.id);
1092*d9f75844SAndroid Build Coastguard Worker // Search for the matching rtx or red codec.
1093*d9f75844SAndroid Build Coastguard Worker if (want_red || want_rtx) {
1094*d9f75844SAndroid Build Coastguard Worker for (const auto& codec : codecs) {
1095*d9f75844SAndroid Build Coastguard Worker if (IsRtxCodec(codec)) {
1096*d9f75844SAndroid Build Coastguard Worker const auto apt =
1097*d9f75844SAndroid Build Coastguard Worker codec.params.find(cricket::kCodecParamAssociatedPayloadType);
1098*d9f75844SAndroid Build Coastguard Worker if (apt != codec.params.end() && apt->second == id) {
1099*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(codec);
1100*d9f75844SAndroid Build Coastguard Worker break;
1101*d9f75844SAndroid Build Coastguard Worker }
1102*d9f75844SAndroid Build Coastguard Worker } else if (IsRedCodec(codec)) {
1103*d9f75844SAndroid Build Coastguard Worker // For RED, do not insert the codec again if it was already
1104*d9f75844SAndroid Build Coastguard Worker // inserted. audio/red for opus gets enabled by having RED before
1105*d9f75844SAndroid Build Coastguard Worker // the primary codec.
1106*d9f75844SAndroid Build Coastguard Worker const auto fmtp =
1107*d9f75844SAndroid Build Coastguard Worker codec.params.find(cricket::kCodecParamNotInNameValueFormat);
1108*d9f75844SAndroid Build Coastguard Worker if (fmtp != codec.params.end()) {
1109*d9f75844SAndroid Build Coastguard Worker std::vector<absl::string_view> redundant_payloads =
1110*d9f75844SAndroid Build Coastguard Worker rtc::split(fmtp->second, '/');
1111*d9f75844SAndroid Build Coastguard Worker if (redundant_payloads.size() > 0 &&
1112*d9f75844SAndroid Build Coastguard Worker redundant_payloads[0] == id) {
1113*d9f75844SAndroid Build Coastguard Worker if (std::find(filtered_codecs.begin(), filtered_codecs.end(),
1114*d9f75844SAndroid Build Coastguard Worker codec) == filtered_codecs.end()) {
1115*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(codec);
1116*d9f75844SAndroid Build Coastguard Worker }
1117*d9f75844SAndroid Build Coastguard Worker break;
1118*d9f75844SAndroid Build Coastguard Worker }
1119*d9f75844SAndroid Build Coastguard Worker }
1120*d9f75844SAndroid Build Coastguard Worker }
1121*d9f75844SAndroid Build Coastguard Worker }
1122*d9f75844SAndroid Build Coastguard Worker }
1123*d9f75844SAndroid Build Coastguard Worker }
1124*d9f75844SAndroid Build Coastguard Worker }
1125*d9f75844SAndroid Build Coastguard Worker }
1126*d9f75844SAndroid Build Coastguard Worker
1127*d9f75844SAndroid Build Coastguard Worker return filtered_codecs;
1128*d9f75844SAndroid Build Coastguard Worker }
1129*d9f75844SAndroid Build Coastguard Worker
1130*d9f75844SAndroid Build Coastguard Worker // Compute the union of `codecs1` and `codecs2`.
1131*d9f75844SAndroid Build Coastguard Worker template <class C>
ComputeCodecsUnion(const std::vector<C> & codecs1,const std::vector<C> & codecs2,const webrtc::FieldTrialsView * field_trials)1132*d9f75844SAndroid Build Coastguard Worker std::vector<C> ComputeCodecsUnion(const std::vector<C>& codecs1,
1133*d9f75844SAndroid Build Coastguard Worker const std::vector<C>& codecs2,
1134*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials) {
1135*d9f75844SAndroid Build Coastguard Worker std::vector<C> all_codecs;
1136*d9f75844SAndroid Build Coastguard Worker UsedPayloadTypes used_payload_types;
1137*d9f75844SAndroid Build Coastguard Worker for (const C& codec : codecs1) {
1138*d9f75844SAndroid Build Coastguard Worker C codec_mutable = codec;
1139*d9f75844SAndroid Build Coastguard Worker used_payload_types.FindAndSetIdUsed(&codec_mutable);
1140*d9f75844SAndroid Build Coastguard Worker all_codecs.push_back(codec_mutable);
1141*d9f75844SAndroid Build Coastguard Worker }
1142*d9f75844SAndroid Build Coastguard Worker
1143*d9f75844SAndroid Build Coastguard Worker // Use MergeCodecs to merge the second half of our list as it already checks
1144*d9f75844SAndroid Build Coastguard Worker // and fixes problems with duplicate payload types.
1145*d9f75844SAndroid Build Coastguard Worker MergeCodecs<C>(codecs2, &all_codecs, &used_payload_types, field_trials);
1146*d9f75844SAndroid Build Coastguard Worker
1147*d9f75844SAndroid Build Coastguard Worker return all_codecs;
1148*d9f75844SAndroid Build Coastguard Worker }
1149*d9f75844SAndroid Build Coastguard Worker
1150*d9f75844SAndroid Build Coastguard Worker // Adds all extensions from `reference_extensions` to `offered_extensions` that
1151*d9f75844SAndroid Build Coastguard Worker // don't already exist in `offered_extensions` and ensure the IDs don't
1152*d9f75844SAndroid Build Coastguard Worker // collide. If an extension is added, it's also added to `regular_extensions` or
1153*d9f75844SAndroid Build Coastguard Worker // `encrypted_extensions`, and if the extension is in `regular_extensions` or
1154*d9f75844SAndroid Build Coastguard Worker // `encrypted_extensions`, its ID is marked as used in `used_ids`.
1155*d9f75844SAndroid Build Coastguard Worker // `offered_extensions` is for either audio or video while `regular_extensions`
1156*d9f75844SAndroid Build Coastguard Worker // and `encrypted_extensions` are used for both audio and video. There could be
1157*d9f75844SAndroid Build Coastguard Worker // overlap between audio extensions and video extensions.
MergeRtpHdrExts(const RtpHeaderExtensions & reference_extensions,RtpHeaderExtensions * offered_extensions,RtpHeaderExtensions * regular_extensions,RtpHeaderExtensions * encrypted_extensions,UsedRtpHeaderExtensionIds * used_ids)1158*d9f75844SAndroid Build Coastguard Worker static void MergeRtpHdrExts(const RtpHeaderExtensions& reference_extensions,
1159*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions* offered_extensions,
1160*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions* regular_extensions,
1161*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions* encrypted_extensions,
1162*d9f75844SAndroid Build Coastguard Worker UsedRtpHeaderExtensionIds* used_ids) {
1163*d9f75844SAndroid Build Coastguard Worker for (auto reference_extension : reference_extensions) {
1164*d9f75844SAndroid Build Coastguard Worker if (!webrtc::RtpExtension::FindHeaderExtensionByUriAndEncryption(
1165*d9f75844SAndroid Build Coastguard Worker *offered_extensions, reference_extension.uri,
1166*d9f75844SAndroid Build Coastguard Worker reference_extension.encrypt)) {
1167*d9f75844SAndroid Build Coastguard Worker if (reference_extension.encrypt) {
1168*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* existing =
1169*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::FindHeaderExtensionByUriAndEncryption(
1170*d9f75844SAndroid Build Coastguard Worker *encrypted_extensions, reference_extension.uri,
1171*d9f75844SAndroid Build Coastguard Worker reference_extension.encrypt);
1172*d9f75844SAndroid Build Coastguard Worker if (existing) {
1173*d9f75844SAndroid Build Coastguard Worker offered_extensions->push_back(*existing);
1174*d9f75844SAndroid Build Coastguard Worker } else {
1175*d9f75844SAndroid Build Coastguard Worker used_ids->FindAndSetIdUsed(&reference_extension);
1176*d9f75844SAndroid Build Coastguard Worker encrypted_extensions->push_back(reference_extension);
1177*d9f75844SAndroid Build Coastguard Worker offered_extensions->push_back(reference_extension);
1178*d9f75844SAndroid Build Coastguard Worker }
1179*d9f75844SAndroid Build Coastguard Worker } else {
1180*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* existing =
1181*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::FindHeaderExtensionByUriAndEncryption(
1182*d9f75844SAndroid Build Coastguard Worker *regular_extensions, reference_extension.uri,
1183*d9f75844SAndroid Build Coastguard Worker reference_extension.encrypt);
1184*d9f75844SAndroid Build Coastguard Worker if (existing) {
1185*d9f75844SAndroid Build Coastguard Worker offered_extensions->push_back(*existing);
1186*d9f75844SAndroid Build Coastguard Worker } else {
1187*d9f75844SAndroid Build Coastguard Worker used_ids->FindAndSetIdUsed(&reference_extension);
1188*d9f75844SAndroid Build Coastguard Worker regular_extensions->push_back(reference_extension);
1189*d9f75844SAndroid Build Coastguard Worker offered_extensions->push_back(reference_extension);
1190*d9f75844SAndroid Build Coastguard Worker }
1191*d9f75844SAndroid Build Coastguard Worker }
1192*d9f75844SAndroid Build Coastguard Worker }
1193*d9f75844SAndroid Build Coastguard Worker }
1194*d9f75844SAndroid Build Coastguard Worker }
1195*d9f75844SAndroid Build Coastguard Worker
AddEncryptedVersionsOfHdrExts(RtpHeaderExtensions * offered_extensions,RtpHeaderExtensions * encrypted_extensions,UsedRtpHeaderExtensionIds * used_ids)1196*d9f75844SAndroid Build Coastguard Worker static void AddEncryptedVersionsOfHdrExts(
1197*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions* offered_extensions,
1198*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions* encrypted_extensions,
1199*d9f75844SAndroid Build Coastguard Worker UsedRtpHeaderExtensionIds* used_ids) {
1200*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions encrypted_extensions_to_add;
1201*d9f75844SAndroid Build Coastguard Worker for (const auto& extension : *offered_extensions) {
1202*d9f75844SAndroid Build Coastguard Worker // Skip existing encrypted offered extension
1203*d9f75844SAndroid Build Coastguard Worker if (extension.encrypt) {
1204*d9f75844SAndroid Build Coastguard Worker continue;
1205*d9f75844SAndroid Build Coastguard Worker }
1206*d9f75844SAndroid Build Coastguard Worker
1207*d9f75844SAndroid Build Coastguard Worker // Skip if we cannot encrypt the extension
1208*d9f75844SAndroid Build Coastguard Worker if (!webrtc::RtpExtension::IsEncryptionSupported(extension.uri)) {
1209*d9f75844SAndroid Build Coastguard Worker continue;
1210*d9f75844SAndroid Build Coastguard Worker }
1211*d9f75844SAndroid Build Coastguard Worker
1212*d9f75844SAndroid Build Coastguard Worker // Skip if an encrypted extension with that URI already exists in the
1213*d9f75844SAndroid Build Coastguard Worker // offered extensions.
1214*d9f75844SAndroid Build Coastguard Worker const bool have_encrypted_extension =
1215*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::FindHeaderExtensionByUriAndEncryption(
1216*d9f75844SAndroid Build Coastguard Worker *offered_extensions, extension.uri, true);
1217*d9f75844SAndroid Build Coastguard Worker if (have_encrypted_extension) {
1218*d9f75844SAndroid Build Coastguard Worker continue;
1219*d9f75844SAndroid Build Coastguard Worker }
1220*d9f75844SAndroid Build Coastguard Worker
1221*d9f75844SAndroid Build Coastguard Worker // Determine if a shared encrypted extension with that URI already exists.
1222*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* shared_encrypted_extension =
1223*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::FindHeaderExtensionByUriAndEncryption(
1224*d9f75844SAndroid Build Coastguard Worker *encrypted_extensions, extension.uri, true);
1225*d9f75844SAndroid Build Coastguard Worker if (shared_encrypted_extension) {
1226*d9f75844SAndroid Build Coastguard Worker // Re-use the shared encrypted extension
1227*d9f75844SAndroid Build Coastguard Worker encrypted_extensions_to_add.push_back(*shared_encrypted_extension);
1228*d9f75844SAndroid Build Coastguard Worker continue;
1229*d9f75844SAndroid Build Coastguard Worker }
1230*d9f75844SAndroid Build Coastguard Worker
1231*d9f75844SAndroid Build Coastguard Worker // None exists. Create a new shared encrypted extension from the
1232*d9f75844SAndroid Build Coastguard Worker // non-encrypted one.
1233*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension new_encrypted_extension(extension);
1234*d9f75844SAndroid Build Coastguard Worker new_encrypted_extension.encrypt = true;
1235*d9f75844SAndroid Build Coastguard Worker used_ids->FindAndSetIdUsed(&new_encrypted_extension);
1236*d9f75844SAndroid Build Coastguard Worker encrypted_extensions->push_back(new_encrypted_extension);
1237*d9f75844SAndroid Build Coastguard Worker encrypted_extensions_to_add.push_back(new_encrypted_extension);
1238*d9f75844SAndroid Build Coastguard Worker }
1239*d9f75844SAndroid Build Coastguard Worker
1240*d9f75844SAndroid Build Coastguard Worker // Append the additional encrypted extensions to be offered
1241*d9f75844SAndroid Build Coastguard Worker offered_extensions->insert(offered_extensions->end(),
1242*d9f75844SAndroid Build Coastguard Worker encrypted_extensions_to_add.begin(),
1243*d9f75844SAndroid Build Coastguard Worker encrypted_extensions_to_add.end());
1244*d9f75844SAndroid Build Coastguard Worker }
1245*d9f75844SAndroid Build Coastguard Worker
1246*d9f75844SAndroid Build Coastguard Worker // Mostly identical to RtpExtension::FindHeaderExtensionByUri but discards any
1247*d9f75844SAndroid Build Coastguard Worker // encrypted extensions that this implementation cannot encrypt.
FindHeaderExtensionByUriDiscardUnsupported(const std::vector<webrtc::RtpExtension> & extensions,absl::string_view uri,webrtc::RtpExtension::Filter filter)1248*d9f75844SAndroid Build Coastguard Worker static const webrtc::RtpExtension* FindHeaderExtensionByUriDiscardUnsupported(
1249*d9f75844SAndroid Build Coastguard Worker const std::vector<webrtc::RtpExtension>& extensions,
1250*d9f75844SAndroid Build Coastguard Worker absl::string_view uri,
1251*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::Filter filter) {
1252*d9f75844SAndroid Build Coastguard Worker // Note: While it's technically possible to decrypt extensions that we don't
1253*d9f75844SAndroid Build Coastguard Worker // encrypt, the symmetric API of libsrtp does not allow us to supply
1254*d9f75844SAndroid Build Coastguard Worker // different IDs for encryption/decryption of header extensions depending on
1255*d9f75844SAndroid Build Coastguard Worker // whether the packet is inbound or outbound. Thereby, we are limited to
1256*d9f75844SAndroid Build Coastguard Worker // what we can send in encrypted form.
1257*d9f75844SAndroid Build Coastguard Worker if (!webrtc::RtpExtension::IsEncryptionSupported(uri)) {
1258*d9f75844SAndroid Build Coastguard Worker // If there's no encryption support and we only want encrypted extensions,
1259*d9f75844SAndroid Build Coastguard Worker // there's no point in continuing the search here.
1260*d9f75844SAndroid Build Coastguard Worker if (filter == webrtc::RtpExtension::kRequireEncryptedExtension) {
1261*d9f75844SAndroid Build Coastguard Worker return nullptr;
1262*d9f75844SAndroid Build Coastguard Worker }
1263*d9f75844SAndroid Build Coastguard Worker
1264*d9f75844SAndroid Build Coastguard Worker // Instruct to only return non-encrypted extensions
1265*d9f75844SAndroid Build Coastguard Worker filter = webrtc::RtpExtension::Filter::kDiscardEncryptedExtension;
1266*d9f75844SAndroid Build Coastguard Worker }
1267*d9f75844SAndroid Build Coastguard Worker
1268*d9f75844SAndroid Build Coastguard Worker return webrtc::RtpExtension::FindHeaderExtensionByUri(extensions, uri,
1269*d9f75844SAndroid Build Coastguard Worker filter);
1270*d9f75844SAndroid Build Coastguard Worker }
1271*d9f75844SAndroid Build Coastguard Worker
NegotiateRtpHeaderExtensions(const RtpHeaderExtensions & local_extensions,const RtpHeaderExtensions & offered_extensions,webrtc::RtpExtension::Filter filter,RtpHeaderExtensions * negotiated_extensions)1272*d9f75844SAndroid Build Coastguard Worker static void NegotiateRtpHeaderExtensions(
1273*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& local_extensions,
1274*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& offered_extensions,
1275*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::Filter filter,
1276*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions* negotiated_extensions) {
1277*d9f75844SAndroid Build Coastguard Worker // TransportSequenceNumberV2 is not offered by default. The special logic for
1278*d9f75844SAndroid Build Coastguard Worker // the TransportSequenceNumber extensions works as follows:
1279*d9f75844SAndroid Build Coastguard Worker // Offer Answer
1280*d9f75844SAndroid Build Coastguard Worker // V1 V1 if in local_extensions.
1281*d9f75844SAndroid Build Coastguard Worker // V1 and V2 V2 regardless of local_extensions.
1282*d9f75844SAndroid Build Coastguard Worker // V2 V2 regardless of local_extensions.
1283*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* transport_sequence_number_v2_offer =
1284*d9f75844SAndroid Build Coastguard Worker FindHeaderExtensionByUriDiscardUnsupported(
1285*d9f75844SAndroid Build Coastguard Worker offered_extensions,
1286*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::kTransportSequenceNumberV2Uri, filter);
1287*d9f75844SAndroid Build Coastguard Worker
1288*d9f75844SAndroid Build Coastguard Worker bool frame_descriptor_in_local = false;
1289*d9f75844SAndroid Build Coastguard Worker bool dependency_descriptor_in_local = false;
1290*d9f75844SAndroid Build Coastguard Worker bool abs_capture_time_in_local = false;
1291*d9f75844SAndroid Build Coastguard Worker
1292*d9f75844SAndroid Build Coastguard Worker for (const webrtc::RtpExtension& ours : local_extensions) {
1293*d9f75844SAndroid Build Coastguard Worker if (ours.uri == webrtc::RtpExtension::kGenericFrameDescriptorUri00)
1294*d9f75844SAndroid Build Coastguard Worker frame_descriptor_in_local = true;
1295*d9f75844SAndroid Build Coastguard Worker else if (ours.uri == webrtc::RtpExtension::kDependencyDescriptorUri)
1296*d9f75844SAndroid Build Coastguard Worker dependency_descriptor_in_local = true;
1297*d9f75844SAndroid Build Coastguard Worker else if (ours.uri == webrtc::RtpExtension::kAbsoluteCaptureTimeUri)
1298*d9f75844SAndroid Build Coastguard Worker abs_capture_time_in_local = true;
1299*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* theirs =
1300*d9f75844SAndroid Build Coastguard Worker FindHeaderExtensionByUriDiscardUnsupported(offered_extensions, ours.uri,
1301*d9f75844SAndroid Build Coastguard Worker filter);
1302*d9f75844SAndroid Build Coastguard Worker if (theirs) {
1303*d9f75844SAndroid Build Coastguard Worker if (transport_sequence_number_v2_offer &&
1304*d9f75844SAndroid Build Coastguard Worker ours.uri == webrtc::RtpExtension::kTransportSequenceNumberUri) {
1305*d9f75844SAndroid Build Coastguard Worker // Don't respond to
1306*d9f75844SAndroid Build Coastguard Worker // http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
1307*d9f75844SAndroid Build Coastguard Worker // if we get an offer including
1308*d9f75844SAndroid Build Coastguard Worker // http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02
1309*d9f75844SAndroid Build Coastguard Worker continue;
1310*d9f75844SAndroid Build Coastguard Worker } else {
1311*d9f75844SAndroid Build Coastguard Worker // We respond with their RTP header extension id.
1312*d9f75844SAndroid Build Coastguard Worker negotiated_extensions->push_back(*theirs);
1313*d9f75844SAndroid Build Coastguard Worker }
1314*d9f75844SAndroid Build Coastguard Worker }
1315*d9f75844SAndroid Build Coastguard Worker }
1316*d9f75844SAndroid Build Coastguard Worker
1317*d9f75844SAndroid Build Coastguard Worker if (transport_sequence_number_v2_offer) {
1318*d9f75844SAndroid Build Coastguard Worker // Respond that we support kTransportSequenceNumberV2Uri.
1319*d9f75844SAndroid Build Coastguard Worker negotiated_extensions->push_back(*transport_sequence_number_v2_offer);
1320*d9f75844SAndroid Build Coastguard Worker }
1321*d9f75844SAndroid Build Coastguard Worker
1322*d9f75844SAndroid Build Coastguard Worker // Frame descriptors support. If the extension is not present locally, but is
1323*d9f75844SAndroid Build Coastguard Worker // in the offer, we add it to the list.
1324*d9f75844SAndroid Build Coastguard Worker if (!dependency_descriptor_in_local) {
1325*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* theirs =
1326*d9f75844SAndroid Build Coastguard Worker FindHeaderExtensionByUriDiscardUnsupported(
1327*d9f75844SAndroid Build Coastguard Worker offered_extensions, webrtc::RtpExtension::kDependencyDescriptorUri,
1328*d9f75844SAndroid Build Coastguard Worker filter);
1329*d9f75844SAndroid Build Coastguard Worker if (theirs) {
1330*d9f75844SAndroid Build Coastguard Worker negotiated_extensions->push_back(*theirs);
1331*d9f75844SAndroid Build Coastguard Worker }
1332*d9f75844SAndroid Build Coastguard Worker }
1333*d9f75844SAndroid Build Coastguard Worker if (!frame_descriptor_in_local) {
1334*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* theirs =
1335*d9f75844SAndroid Build Coastguard Worker FindHeaderExtensionByUriDiscardUnsupported(
1336*d9f75844SAndroid Build Coastguard Worker offered_extensions,
1337*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::kGenericFrameDescriptorUri00, filter);
1338*d9f75844SAndroid Build Coastguard Worker if (theirs) {
1339*d9f75844SAndroid Build Coastguard Worker negotiated_extensions->push_back(*theirs);
1340*d9f75844SAndroid Build Coastguard Worker }
1341*d9f75844SAndroid Build Coastguard Worker }
1342*d9f75844SAndroid Build Coastguard Worker
1343*d9f75844SAndroid Build Coastguard Worker // Absolute capture time support. If the extension is not present locally, but
1344*d9f75844SAndroid Build Coastguard Worker // is in the offer, we add it to the list.
1345*d9f75844SAndroid Build Coastguard Worker if (!abs_capture_time_in_local) {
1346*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension* theirs =
1347*d9f75844SAndroid Build Coastguard Worker FindHeaderExtensionByUriDiscardUnsupported(
1348*d9f75844SAndroid Build Coastguard Worker offered_extensions, webrtc::RtpExtension::kAbsoluteCaptureTimeUri,
1349*d9f75844SAndroid Build Coastguard Worker filter);
1350*d9f75844SAndroid Build Coastguard Worker if (theirs) {
1351*d9f75844SAndroid Build Coastguard Worker negotiated_extensions->push_back(*theirs);
1352*d9f75844SAndroid Build Coastguard Worker }
1353*d9f75844SAndroid Build Coastguard Worker }
1354*d9f75844SAndroid Build Coastguard Worker }
1355*d9f75844SAndroid Build Coastguard Worker
StripCNCodecs(AudioCodecs * audio_codecs)1356*d9f75844SAndroid Build Coastguard Worker static void StripCNCodecs(AudioCodecs* audio_codecs) {
1357*d9f75844SAndroid Build Coastguard Worker audio_codecs->erase(std::remove_if(audio_codecs->begin(), audio_codecs->end(),
1358*d9f75844SAndroid Build Coastguard Worker [](const AudioCodec& codec) {
1359*d9f75844SAndroid Build Coastguard Worker return IsComfortNoiseCodec(codec);
1360*d9f75844SAndroid Build Coastguard Worker }),
1361*d9f75844SAndroid Build Coastguard Worker audio_codecs->end());
1362*d9f75844SAndroid Build Coastguard Worker }
1363*d9f75844SAndroid Build Coastguard Worker
1364*d9f75844SAndroid Build Coastguard Worker template <class C>
SetCodecsInAnswer(const MediaContentDescriptionImpl<C> * offer,const std::vector<C> & local_codecs,const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,UniqueRandomIdGenerator * ssrc_generator,StreamParamsVec * current_streams,MediaContentDescriptionImpl<C> * answer,const webrtc::FieldTrialsView & field_trials)1365*d9f75844SAndroid Build Coastguard Worker static bool SetCodecsInAnswer(
1366*d9f75844SAndroid Build Coastguard Worker const MediaContentDescriptionImpl<C>* offer,
1367*d9f75844SAndroid Build Coastguard Worker const std::vector<C>& local_codecs,
1368*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
1369*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
1370*d9f75844SAndroid Build Coastguard Worker UniqueRandomIdGenerator* ssrc_generator,
1371*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
1372*d9f75844SAndroid Build Coastguard Worker MediaContentDescriptionImpl<C>* answer,
1373*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView& field_trials) {
1374*d9f75844SAndroid Build Coastguard Worker std::vector<C> negotiated_codecs;
1375*d9f75844SAndroid Build Coastguard Worker NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs,
1376*d9f75844SAndroid Build Coastguard Worker media_description_options.codec_preferences.empty(),
1377*d9f75844SAndroid Build Coastguard Worker &field_trials);
1378*d9f75844SAndroid Build Coastguard Worker answer->AddCodecs(negotiated_codecs);
1379*d9f75844SAndroid Build Coastguard Worker answer->set_protocol(offer->protocol());
1380*d9f75844SAndroid Build Coastguard Worker if (!AddStreamParams(media_description_options.sender_options,
1381*d9f75844SAndroid Build Coastguard Worker session_options.rtcp_cname, ssrc_generator,
1382*d9f75844SAndroid Build Coastguard Worker current_streams, answer, field_trials)) {
1383*d9f75844SAndroid Build Coastguard Worker return false; // Something went seriously wrong.
1384*d9f75844SAndroid Build Coastguard Worker }
1385*d9f75844SAndroid Build Coastguard Worker return true;
1386*d9f75844SAndroid Build Coastguard Worker }
1387*d9f75844SAndroid Build Coastguard Worker
1388*d9f75844SAndroid Build Coastguard Worker // Create a media content to be answered for the given `sender_options`
1389*d9f75844SAndroid Build Coastguard Worker // according to the given session_options.rtcp_mux, session_options.streams,
1390*d9f75844SAndroid Build Coastguard Worker // codecs, crypto, and current_streams. If we don't currently have crypto (in
1391*d9f75844SAndroid Build Coastguard Worker // current_cryptos) and it is enabled (in secure_policy), crypto is created
1392*d9f75844SAndroid Build Coastguard Worker // (according to crypto_suites). The codecs, rtcp_mux, and crypto are all
1393*d9f75844SAndroid Build Coastguard Worker // negotiated with the offer. If the negotiation fails, this method returns
1394*d9f75844SAndroid Build Coastguard Worker // false. The created content is added to the offer.
CreateMediaContentAnswer(const MediaContentDescription * offer,const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const SecurePolicy & sdes_policy,const CryptoParamsVec * current_cryptos,const RtpHeaderExtensions & local_rtp_extensions,UniqueRandomIdGenerator * ssrc_generator,bool enable_encrypted_rtp_header_extensions,StreamParamsVec * current_streams,bool bundle_enabled,MediaContentDescription * answer)1395*d9f75844SAndroid Build Coastguard Worker static bool CreateMediaContentAnswer(
1396*d9f75844SAndroid Build Coastguard Worker const MediaContentDescription* offer,
1397*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
1398*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
1399*d9f75844SAndroid Build Coastguard Worker const SecurePolicy& sdes_policy,
1400*d9f75844SAndroid Build Coastguard Worker const CryptoParamsVec* current_cryptos,
1401*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& local_rtp_extensions,
1402*d9f75844SAndroid Build Coastguard Worker UniqueRandomIdGenerator* ssrc_generator,
1403*d9f75844SAndroid Build Coastguard Worker bool enable_encrypted_rtp_header_extensions,
1404*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
1405*d9f75844SAndroid Build Coastguard Worker bool bundle_enabled,
1406*d9f75844SAndroid Build Coastguard Worker MediaContentDescription* answer) {
1407*d9f75844SAndroid Build Coastguard Worker answer->set_extmap_allow_mixed_enum(offer->extmap_allow_mixed_enum());
1408*d9f75844SAndroid Build Coastguard Worker const webrtc::RtpExtension::Filter extensions_filter =
1409*d9f75844SAndroid Build Coastguard Worker enable_encrypted_rtp_header_extensions
1410*d9f75844SAndroid Build Coastguard Worker ? webrtc::RtpExtension::Filter::kPreferEncryptedExtension
1411*d9f75844SAndroid Build Coastguard Worker : webrtc::RtpExtension::Filter::kDiscardEncryptedExtension;
1412*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions negotiated_rtp_extensions;
1413*d9f75844SAndroid Build Coastguard Worker NegotiateRtpHeaderExtensions(local_rtp_extensions,
1414*d9f75844SAndroid Build Coastguard Worker offer->rtp_header_extensions(),
1415*d9f75844SAndroid Build Coastguard Worker extensions_filter, &negotiated_rtp_extensions);
1416*d9f75844SAndroid Build Coastguard Worker answer->set_rtp_header_extensions(negotiated_rtp_extensions);
1417*d9f75844SAndroid Build Coastguard Worker
1418*d9f75844SAndroid Build Coastguard Worker answer->set_rtcp_mux(session_options.rtcp_mux_enabled && offer->rtcp_mux());
1419*d9f75844SAndroid Build Coastguard Worker if (answer->type() == cricket::MEDIA_TYPE_VIDEO) {
1420*d9f75844SAndroid Build Coastguard Worker answer->set_rtcp_reduced_size(offer->rtcp_reduced_size());
1421*d9f75844SAndroid Build Coastguard Worker }
1422*d9f75844SAndroid Build Coastguard Worker
1423*d9f75844SAndroid Build Coastguard Worker answer->set_remote_estimate(offer->remote_estimate());
1424*d9f75844SAndroid Build Coastguard Worker
1425*d9f75844SAndroid Build Coastguard Worker if (sdes_policy != SEC_DISABLED) {
1426*d9f75844SAndroid Build Coastguard Worker CryptoParams crypto;
1427*d9f75844SAndroid Build Coastguard Worker if (SelectCrypto(offer, bundle_enabled, session_options.crypto_options,
1428*d9f75844SAndroid Build Coastguard Worker &crypto)) {
1429*d9f75844SAndroid Build Coastguard Worker if (current_cryptos) {
1430*d9f75844SAndroid Build Coastguard Worker FindMatchingCrypto(*current_cryptos, crypto, &crypto);
1431*d9f75844SAndroid Build Coastguard Worker }
1432*d9f75844SAndroid Build Coastguard Worker answer->AddCrypto(crypto);
1433*d9f75844SAndroid Build Coastguard Worker }
1434*d9f75844SAndroid Build Coastguard Worker }
1435*d9f75844SAndroid Build Coastguard Worker
1436*d9f75844SAndroid Build Coastguard Worker if (answer->cryptos().empty() && sdes_policy == SEC_REQUIRED) {
1437*d9f75844SAndroid Build Coastguard Worker return false;
1438*d9f75844SAndroid Build Coastguard Worker }
1439*d9f75844SAndroid Build Coastguard Worker
1440*d9f75844SAndroid Build Coastguard Worker AddSimulcastToMediaDescription(media_description_options, answer);
1441*d9f75844SAndroid Build Coastguard Worker
1442*d9f75844SAndroid Build Coastguard Worker answer->set_direction(NegotiateRtpTransceiverDirection(
1443*d9f75844SAndroid Build Coastguard Worker offer->direction(), media_description_options.direction));
1444*d9f75844SAndroid Build Coastguard Worker
1445*d9f75844SAndroid Build Coastguard Worker return true;
1446*d9f75844SAndroid Build Coastguard Worker }
1447*d9f75844SAndroid Build Coastguard Worker
IsMediaProtocolSupported(MediaType type,const std::string & protocol,bool secure_transport)1448*d9f75844SAndroid Build Coastguard Worker static bool IsMediaProtocolSupported(MediaType type,
1449*d9f75844SAndroid Build Coastguard Worker const std::string& protocol,
1450*d9f75844SAndroid Build Coastguard Worker bool secure_transport) {
1451*d9f75844SAndroid Build Coastguard Worker // Since not all applications serialize and deserialize the media protocol,
1452*d9f75844SAndroid Build Coastguard Worker // we will have to accept `protocol` to be empty.
1453*d9f75844SAndroid Build Coastguard Worker if (protocol.empty()) {
1454*d9f75844SAndroid Build Coastguard Worker return true;
1455*d9f75844SAndroid Build Coastguard Worker }
1456*d9f75844SAndroid Build Coastguard Worker
1457*d9f75844SAndroid Build Coastguard Worker if (type == MEDIA_TYPE_DATA) {
1458*d9f75844SAndroid Build Coastguard Worker // Check for SCTP
1459*d9f75844SAndroid Build Coastguard Worker if (secure_transport) {
1460*d9f75844SAndroid Build Coastguard Worker // Most likely scenarios first.
1461*d9f75844SAndroid Build Coastguard Worker return IsDtlsSctp(protocol);
1462*d9f75844SAndroid Build Coastguard Worker } else {
1463*d9f75844SAndroid Build Coastguard Worker return IsPlainSctp(protocol);
1464*d9f75844SAndroid Build Coastguard Worker }
1465*d9f75844SAndroid Build Coastguard Worker }
1466*d9f75844SAndroid Build Coastguard Worker
1467*d9f75844SAndroid Build Coastguard Worker // Allow for non-DTLS RTP protocol even when using DTLS because that's what
1468*d9f75844SAndroid Build Coastguard Worker // JSEP specifies.
1469*d9f75844SAndroid Build Coastguard Worker if (secure_transport) {
1470*d9f75844SAndroid Build Coastguard Worker // Most likely scenarios first.
1471*d9f75844SAndroid Build Coastguard Worker return IsDtlsRtp(protocol) || IsPlainRtp(protocol);
1472*d9f75844SAndroid Build Coastguard Worker } else {
1473*d9f75844SAndroid Build Coastguard Worker return IsPlainRtp(protocol);
1474*d9f75844SAndroid Build Coastguard Worker }
1475*d9f75844SAndroid Build Coastguard Worker }
1476*d9f75844SAndroid Build Coastguard Worker
SetMediaProtocol(bool secure_transport,MediaContentDescription * desc)1477*d9f75844SAndroid Build Coastguard Worker static void SetMediaProtocol(bool secure_transport,
1478*d9f75844SAndroid Build Coastguard Worker MediaContentDescription* desc) {
1479*d9f75844SAndroid Build Coastguard Worker if (!desc->cryptos().empty())
1480*d9f75844SAndroid Build Coastguard Worker desc->set_protocol(kMediaProtocolSavpf);
1481*d9f75844SAndroid Build Coastguard Worker else if (secure_transport)
1482*d9f75844SAndroid Build Coastguard Worker desc->set_protocol(kMediaProtocolDtlsSavpf);
1483*d9f75844SAndroid Build Coastguard Worker else
1484*d9f75844SAndroid Build Coastguard Worker desc->set_protocol(kMediaProtocolAvpf);
1485*d9f75844SAndroid Build Coastguard Worker }
1486*d9f75844SAndroid Build Coastguard Worker
1487*d9f75844SAndroid Build Coastguard Worker // Gets the TransportInfo of the given `content_name` from the
1488*d9f75844SAndroid Build Coastguard Worker // `current_description`. If doesn't exist, returns a new one.
GetTransportDescription(const std::string & content_name,const SessionDescription * current_description)1489*d9f75844SAndroid Build Coastguard Worker static const TransportDescription* GetTransportDescription(
1490*d9f75844SAndroid Build Coastguard Worker const std::string& content_name,
1491*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description) {
1492*d9f75844SAndroid Build Coastguard Worker const TransportDescription* desc = NULL;
1493*d9f75844SAndroid Build Coastguard Worker if (current_description) {
1494*d9f75844SAndroid Build Coastguard Worker const TransportInfo* info =
1495*d9f75844SAndroid Build Coastguard Worker current_description->GetTransportInfoByName(content_name);
1496*d9f75844SAndroid Build Coastguard Worker if (info) {
1497*d9f75844SAndroid Build Coastguard Worker desc = &info->description;
1498*d9f75844SAndroid Build Coastguard Worker }
1499*d9f75844SAndroid Build Coastguard Worker }
1500*d9f75844SAndroid Build Coastguard Worker return desc;
1501*d9f75844SAndroid Build Coastguard Worker }
1502*d9f75844SAndroid Build Coastguard Worker
1503*d9f75844SAndroid Build Coastguard Worker // Gets the current DTLS state from the transport description.
IsDtlsActive(const ContentInfo * content,const SessionDescription * current_description)1504*d9f75844SAndroid Build Coastguard Worker static bool IsDtlsActive(const ContentInfo* content,
1505*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description) {
1506*d9f75844SAndroid Build Coastguard Worker if (!content) {
1507*d9f75844SAndroid Build Coastguard Worker return false;
1508*d9f75844SAndroid Build Coastguard Worker }
1509*d9f75844SAndroid Build Coastguard Worker
1510*d9f75844SAndroid Build Coastguard Worker size_t msection_index = content - ¤t_description->contents()[0];
1511*d9f75844SAndroid Build Coastguard Worker
1512*d9f75844SAndroid Build Coastguard Worker if (current_description->transport_infos().size() <= msection_index) {
1513*d9f75844SAndroid Build Coastguard Worker return false;
1514*d9f75844SAndroid Build Coastguard Worker }
1515*d9f75844SAndroid Build Coastguard Worker
1516*d9f75844SAndroid Build Coastguard Worker return current_description->transport_infos()[msection_index]
1517*d9f75844SAndroid Build Coastguard Worker .description.secure();
1518*d9f75844SAndroid Build Coastguard Worker }
1519*d9f75844SAndroid Build Coastguard Worker
AddAudioSender(const std::string & track_id,const std::vector<std::string> & stream_ids)1520*d9f75844SAndroid Build Coastguard Worker void MediaDescriptionOptions::AddAudioSender(
1521*d9f75844SAndroid Build Coastguard Worker const std::string& track_id,
1522*d9f75844SAndroid Build Coastguard Worker const std::vector<std::string>& stream_ids) {
1523*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(type == MEDIA_TYPE_AUDIO);
1524*d9f75844SAndroid Build Coastguard Worker AddSenderInternal(track_id, stream_ids, {}, SimulcastLayerList(), 1);
1525*d9f75844SAndroid Build Coastguard Worker }
1526*d9f75844SAndroid Build Coastguard Worker
AddVideoSender(const std::string & track_id,const std::vector<std::string> & stream_ids,const std::vector<RidDescription> & rids,const SimulcastLayerList & simulcast_layers,int num_sim_layers)1527*d9f75844SAndroid Build Coastguard Worker void MediaDescriptionOptions::AddVideoSender(
1528*d9f75844SAndroid Build Coastguard Worker const std::string& track_id,
1529*d9f75844SAndroid Build Coastguard Worker const std::vector<std::string>& stream_ids,
1530*d9f75844SAndroid Build Coastguard Worker const std::vector<RidDescription>& rids,
1531*d9f75844SAndroid Build Coastguard Worker const SimulcastLayerList& simulcast_layers,
1532*d9f75844SAndroid Build Coastguard Worker int num_sim_layers) {
1533*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(type == MEDIA_TYPE_VIDEO);
1534*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(rids.empty() || num_sim_layers == 0)
1535*d9f75844SAndroid Build Coastguard Worker << "RIDs are the compliant way to indicate simulcast.";
1536*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(ValidateSimulcastLayers(rids, simulcast_layers));
1537*d9f75844SAndroid Build Coastguard Worker AddSenderInternal(track_id, stream_ids, rids, simulcast_layers,
1538*d9f75844SAndroid Build Coastguard Worker num_sim_layers);
1539*d9f75844SAndroid Build Coastguard Worker }
1540*d9f75844SAndroid Build Coastguard Worker
AddSenderInternal(const std::string & track_id,const std::vector<std::string> & stream_ids,const std::vector<RidDescription> & rids,const SimulcastLayerList & simulcast_layers,int num_sim_layers)1541*d9f75844SAndroid Build Coastguard Worker void MediaDescriptionOptions::AddSenderInternal(
1542*d9f75844SAndroid Build Coastguard Worker const std::string& track_id,
1543*d9f75844SAndroid Build Coastguard Worker const std::vector<std::string>& stream_ids,
1544*d9f75844SAndroid Build Coastguard Worker const std::vector<RidDescription>& rids,
1545*d9f75844SAndroid Build Coastguard Worker const SimulcastLayerList& simulcast_layers,
1546*d9f75844SAndroid Build Coastguard Worker int num_sim_layers) {
1547*d9f75844SAndroid Build Coastguard Worker // TODO(steveanton): Support any number of stream ids.
1548*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(stream_ids.size() == 1U);
1549*d9f75844SAndroid Build Coastguard Worker SenderOptions options;
1550*d9f75844SAndroid Build Coastguard Worker options.track_id = track_id;
1551*d9f75844SAndroid Build Coastguard Worker options.stream_ids = stream_ids;
1552*d9f75844SAndroid Build Coastguard Worker options.simulcast_layers = simulcast_layers;
1553*d9f75844SAndroid Build Coastguard Worker options.rids = rids;
1554*d9f75844SAndroid Build Coastguard Worker options.num_sim_layers = num_sim_layers;
1555*d9f75844SAndroid Build Coastguard Worker sender_options.push_back(options);
1556*d9f75844SAndroid Build Coastguard Worker }
1557*d9f75844SAndroid Build Coastguard Worker
HasMediaDescription(MediaType type) const1558*d9f75844SAndroid Build Coastguard Worker bool MediaSessionOptions::HasMediaDescription(MediaType type) const {
1559*d9f75844SAndroid Build Coastguard Worker return absl::c_any_of(
1560*d9f75844SAndroid Build Coastguard Worker media_description_options,
1561*d9f75844SAndroid Build Coastguard Worker [type](const MediaDescriptionOptions& t) { return t.type == type; });
1562*d9f75844SAndroid Build Coastguard Worker }
1563*d9f75844SAndroid Build Coastguard Worker
MediaSessionDescriptionFactory(const TransportDescriptionFactory * transport_desc_factory,rtc::UniqueRandomIdGenerator * ssrc_generator)1564*d9f75844SAndroid Build Coastguard Worker MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
1565*d9f75844SAndroid Build Coastguard Worker const TransportDescriptionFactory* transport_desc_factory,
1566*d9f75844SAndroid Build Coastguard Worker rtc::UniqueRandomIdGenerator* ssrc_generator)
1567*d9f75844SAndroid Build Coastguard Worker : ssrc_generator_(ssrc_generator),
1568*d9f75844SAndroid Build Coastguard Worker transport_desc_factory_(transport_desc_factory) {}
1569*d9f75844SAndroid Build Coastguard Worker
MediaSessionDescriptionFactory(cricket::MediaEngineInterface * media_engine,bool rtx_enabled,rtc::UniqueRandomIdGenerator * ssrc_generator,const TransportDescriptionFactory * transport_desc_factory)1570*d9f75844SAndroid Build Coastguard Worker MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
1571*d9f75844SAndroid Build Coastguard Worker cricket::MediaEngineInterface* media_engine,
1572*d9f75844SAndroid Build Coastguard Worker bool rtx_enabled,
1573*d9f75844SAndroid Build Coastguard Worker rtc::UniqueRandomIdGenerator* ssrc_generator,
1574*d9f75844SAndroid Build Coastguard Worker const TransportDescriptionFactory* transport_desc_factory)
1575*d9f75844SAndroid Build Coastguard Worker : MediaSessionDescriptionFactory(transport_desc_factory, ssrc_generator) {
1576*d9f75844SAndroid Build Coastguard Worker if (media_engine) {
1577*d9f75844SAndroid Build Coastguard Worker audio_send_codecs_ = media_engine->voice().send_codecs();
1578*d9f75844SAndroid Build Coastguard Worker audio_recv_codecs_ = media_engine->voice().recv_codecs();
1579*d9f75844SAndroid Build Coastguard Worker video_send_codecs_ = media_engine->video().send_codecs(rtx_enabled);
1580*d9f75844SAndroid Build Coastguard Worker video_recv_codecs_ = media_engine->video().recv_codecs(rtx_enabled);
1581*d9f75844SAndroid Build Coastguard Worker }
1582*d9f75844SAndroid Build Coastguard Worker ComputeAudioCodecsIntersectionAndUnion();
1583*d9f75844SAndroid Build Coastguard Worker ComputeVideoCodecsIntersectionAndUnion();
1584*d9f75844SAndroid Build Coastguard Worker }
1585*d9f75844SAndroid Build Coastguard Worker
audio_sendrecv_codecs() const1586*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& MediaSessionDescriptionFactory::audio_sendrecv_codecs()
1587*d9f75844SAndroid Build Coastguard Worker const {
1588*d9f75844SAndroid Build Coastguard Worker return audio_sendrecv_codecs_;
1589*d9f75844SAndroid Build Coastguard Worker }
1590*d9f75844SAndroid Build Coastguard Worker
audio_send_codecs() const1591*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& MediaSessionDescriptionFactory::audio_send_codecs() const {
1592*d9f75844SAndroid Build Coastguard Worker return audio_send_codecs_;
1593*d9f75844SAndroid Build Coastguard Worker }
1594*d9f75844SAndroid Build Coastguard Worker
audio_recv_codecs() const1595*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& MediaSessionDescriptionFactory::audio_recv_codecs() const {
1596*d9f75844SAndroid Build Coastguard Worker return audio_recv_codecs_;
1597*d9f75844SAndroid Build Coastguard Worker }
1598*d9f75844SAndroid Build Coastguard Worker
set_audio_codecs(const AudioCodecs & send_codecs,const AudioCodecs & recv_codecs)1599*d9f75844SAndroid Build Coastguard Worker void MediaSessionDescriptionFactory::set_audio_codecs(
1600*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& send_codecs,
1601*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& recv_codecs) {
1602*d9f75844SAndroid Build Coastguard Worker audio_send_codecs_ = send_codecs;
1603*d9f75844SAndroid Build Coastguard Worker audio_recv_codecs_ = recv_codecs;
1604*d9f75844SAndroid Build Coastguard Worker ComputeAudioCodecsIntersectionAndUnion();
1605*d9f75844SAndroid Build Coastguard Worker }
1606*d9f75844SAndroid Build Coastguard Worker
video_sendrecv_codecs() const1607*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& MediaSessionDescriptionFactory::video_sendrecv_codecs()
1608*d9f75844SAndroid Build Coastguard Worker const {
1609*d9f75844SAndroid Build Coastguard Worker return video_sendrecv_codecs_;
1610*d9f75844SAndroid Build Coastguard Worker }
1611*d9f75844SAndroid Build Coastguard Worker
video_send_codecs() const1612*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& MediaSessionDescriptionFactory::video_send_codecs() const {
1613*d9f75844SAndroid Build Coastguard Worker return video_send_codecs_;
1614*d9f75844SAndroid Build Coastguard Worker }
1615*d9f75844SAndroid Build Coastguard Worker
video_recv_codecs() const1616*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& MediaSessionDescriptionFactory::video_recv_codecs() const {
1617*d9f75844SAndroid Build Coastguard Worker return video_recv_codecs_;
1618*d9f75844SAndroid Build Coastguard Worker }
1619*d9f75844SAndroid Build Coastguard Worker
set_video_codecs(const VideoCodecs & send_codecs,const VideoCodecs & recv_codecs)1620*d9f75844SAndroid Build Coastguard Worker void MediaSessionDescriptionFactory::set_video_codecs(
1621*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& send_codecs,
1622*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& recv_codecs) {
1623*d9f75844SAndroid Build Coastguard Worker video_send_codecs_ = send_codecs;
1624*d9f75844SAndroid Build Coastguard Worker video_recv_codecs_ = recv_codecs;
1625*d9f75844SAndroid Build Coastguard Worker ComputeVideoCodecsIntersectionAndUnion();
1626*d9f75844SAndroid Build Coastguard Worker }
1627*d9f75844SAndroid Build Coastguard Worker
RemoveUnifiedPlanExtensions(RtpHeaderExtensions * extensions)1628*d9f75844SAndroid Build Coastguard Worker static void RemoveUnifiedPlanExtensions(RtpHeaderExtensions* extensions) {
1629*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(extensions);
1630*d9f75844SAndroid Build Coastguard Worker
1631*d9f75844SAndroid Build Coastguard Worker extensions->erase(
1632*d9f75844SAndroid Build Coastguard Worker std::remove_if(extensions->begin(), extensions->end(),
1633*d9f75844SAndroid Build Coastguard Worker [](auto extension) {
1634*d9f75844SAndroid Build Coastguard Worker return extension.uri == webrtc::RtpExtension::kMidUri ||
1635*d9f75844SAndroid Build Coastguard Worker extension.uri == webrtc::RtpExtension::kRidUri ||
1636*d9f75844SAndroid Build Coastguard Worker extension.uri ==
1637*d9f75844SAndroid Build Coastguard Worker webrtc::RtpExtension::kRepairedRidUri;
1638*d9f75844SAndroid Build Coastguard Worker }),
1639*d9f75844SAndroid Build Coastguard Worker extensions->end());
1640*d9f75844SAndroid Build Coastguard Worker }
1641*d9f75844SAndroid Build Coastguard Worker
1642*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions
filtered_rtp_header_extensions(RtpHeaderExtensions extensions) const1643*d9f75844SAndroid Build Coastguard Worker MediaSessionDescriptionFactory::filtered_rtp_header_extensions(
1644*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions extensions) const {
1645*d9f75844SAndroid Build Coastguard Worker if (!is_unified_plan_) {
1646*d9f75844SAndroid Build Coastguard Worker RemoveUnifiedPlanExtensions(&extensions);
1647*d9f75844SAndroid Build Coastguard Worker }
1648*d9f75844SAndroid Build Coastguard Worker return extensions;
1649*d9f75844SAndroid Build Coastguard Worker }
1650*d9f75844SAndroid Build Coastguard Worker
CreateOffer(const MediaSessionOptions & session_options,const SessionDescription * current_description) const1651*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer(
1652*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
1653*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description) const {
1654*d9f75844SAndroid Build Coastguard Worker // Must have options for each existing section.
1655*d9f75844SAndroid Build Coastguard Worker if (current_description) {
1656*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_LE(current_description->contents().size(),
1657*d9f75844SAndroid Build Coastguard Worker session_options.media_description_options.size());
1658*d9f75844SAndroid Build Coastguard Worker }
1659*d9f75844SAndroid Build Coastguard Worker
1660*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator ice_credentials(
1661*d9f75844SAndroid Build Coastguard Worker session_options.pooled_ice_credentials);
1662*d9f75844SAndroid Build Coastguard Worker
1663*d9f75844SAndroid Build Coastguard Worker std::vector<const ContentInfo*> current_active_contents;
1664*d9f75844SAndroid Build Coastguard Worker if (current_description) {
1665*d9f75844SAndroid Build Coastguard Worker current_active_contents =
1666*d9f75844SAndroid Build Coastguard Worker GetActiveContents(*current_description, session_options);
1667*d9f75844SAndroid Build Coastguard Worker }
1668*d9f75844SAndroid Build Coastguard Worker
1669*d9f75844SAndroid Build Coastguard Worker StreamParamsVec current_streams =
1670*d9f75844SAndroid Build Coastguard Worker GetCurrentStreamParams(current_active_contents);
1671*d9f75844SAndroid Build Coastguard Worker
1672*d9f75844SAndroid Build Coastguard Worker AudioCodecs offer_audio_codecs;
1673*d9f75844SAndroid Build Coastguard Worker VideoCodecs offer_video_codecs;
1674*d9f75844SAndroid Build Coastguard Worker GetCodecsForOffer(current_active_contents, &offer_audio_codecs,
1675*d9f75844SAndroid Build Coastguard Worker &offer_video_codecs);
1676*d9f75844SAndroid Build Coastguard Worker AudioVideoRtpHeaderExtensions extensions_with_ids =
1677*d9f75844SAndroid Build Coastguard Worker GetOfferedRtpHeaderExtensionsWithIds(
1678*d9f75844SAndroid Build Coastguard Worker current_active_contents, session_options.offer_extmap_allow_mixed,
1679*d9f75844SAndroid Build Coastguard Worker session_options.media_description_options);
1680*d9f75844SAndroid Build Coastguard Worker
1681*d9f75844SAndroid Build Coastguard Worker auto offer = std::make_unique<SessionDescription>();
1682*d9f75844SAndroid Build Coastguard Worker
1683*d9f75844SAndroid Build Coastguard Worker // Iterate through the media description options, matching with existing media
1684*d9f75844SAndroid Build Coastguard Worker // descriptions in `current_description`.
1685*d9f75844SAndroid Build Coastguard Worker size_t msection_index = 0;
1686*d9f75844SAndroid Build Coastguard Worker for (const MediaDescriptionOptions& media_description_options :
1687*d9f75844SAndroid Build Coastguard Worker session_options.media_description_options) {
1688*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content = nullptr;
1689*d9f75844SAndroid Build Coastguard Worker if (current_description &&
1690*d9f75844SAndroid Build Coastguard Worker msection_index < current_description->contents().size()) {
1691*d9f75844SAndroid Build Coastguard Worker current_content = ¤t_description->contents()[msection_index];
1692*d9f75844SAndroid Build Coastguard Worker // Media type must match unless this media section is being recycled.
1693*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(current_content->name != media_description_options.mid ||
1694*d9f75844SAndroid Build Coastguard Worker IsMediaContentOfType(current_content,
1695*d9f75844SAndroid Build Coastguard Worker media_description_options.type));
1696*d9f75844SAndroid Build Coastguard Worker }
1697*d9f75844SAndroid Build Coastguard Worker switch (media_description_options.type) {
1698*d9f75844SAndroid Build Coastguard Worker case MEDIA_TYPE_AUDIO:
1699*d9f75844SAndroid Build Coastguard Worker if (!AddAudioContentForOffer(media_description_options, session_options,
1700*d9f75844SAndroid Build Coastguard Worker current_content, current_description,
1701*d9f75844SAndroid Build Coastguard Worker extensions_with_ids.audio,
1702*d9f75844SAndroid Build Coastguard Worker offer_audio_codecs, ¤t_streams,
1703*d9f75844SAndroid Build Coastguard Worker offer.get(), &ice_credentials)) {
1704*d9f75844SAndroid Build Coastguard Worker return nullptr;
1705*d9f75844SAndroid Build Coastguard Worker }
1706*d9f75844SAndroid Build Coastguard Worker break;
1707*d9f75844SAndroid Build Coastguard Worker case MEDIA_TYPE_VIDEO:
1708*d9f75844SAndroid Build Coastguard Worker if (!AddVideoContentForOffer(media_description_options, session_options,
1709*d9f75844SAndroid Build Coastguard Worker current_content, current_description,
1710*d9f75844SAndroid Build Coastguard Worker extensions_with_ids.video,
1711*d9f75844SAndroid Build Coastguard Worker offer_video_codecs, ¤t_streams,
1712*d9f75844SAndroid Build Coastguard Worker offer.get(), &ice_credentials)) {
1713*d9f75844SAndroid Build Coastguard Worker return nullptr;
1714*d9f75844SAndroid Build Coastguard Worker }
1715*d9f75844SAndroid Build Coastguard Worker break;
1716*d9f75844SAndroid Build Coastguard Worker case MEDIA_TYPE_DATA:
1717*d9f75844SAndroid Build Coastguard Worker if (!AddDataContentForOffer(media_description_options, session_options,
1718*d9f75844SAndroid Build Coastguard Worker current_content, current_description,
1719*d9f75844SAndroid Build Coastguard Worker ¤t_streams, offer.get(),
1720*d9f75844SAndroid Build Coastguard Worker &ice_credentials)) {
1721*d9f75844SAndroid Build Coastguard Worker return nullptr;
1722*d9f75844SAndroid Build Coastguard Worker }
1723*d9f75844SAndroid Build Coastguard Worker break;
1724*d9f75844SAndroid Build Coastguard Worker case MEDIA_TYPE_UNSUPPORTED:
1725*d9f75844SAndroid Build Coastguard Worker if (!AddUnsupportedContentForOffer(
1726*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options, current_content,
1727*d9f75844SAndroid Build Coastguard Worker current_description, offer.get(), &ice_credentials)) {
1728*d9f75844SAndroid Build Coastguard Worker return nullptr;
1729*d9f75844SAndroid Build Coastguard Worker }
1730*d9f75844SAndroid Build Coastguard Worker break;
1731*d9f75844SAndroid Build Coastguard Worker default:
1732*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
1733*d9f75844SAndroid Build Coastguard Worker }
1734*d9f75844SAndroid Build Coastguard Worker ++msection_index;
1735*d9f75844SAndroid Build Coastguard Worker }
1736*d9f75844SAndroid Build Coastguard Worker
1737*d9f75844SAndroid Build Coastguard Worker // Bundle the contents together, if we've been asked to do so, and update any
1738*d9f75844SAndroid Build Coastguard Worker // parameters that need to be tweaked for BUNDLE.
1739*d9f75844SAndroid Build Coastguard Worker if (session_options.bundle_enabled) {
1740*d9f75844SAndroid Build Coastguard Worker ContentGroup offer_bundle(GROUP_TYPE_BUNDLE);
1741*d9f75844SAndroid Build Coastguard Worker for (const ContentInfo& content : offer->contents()) {
1742*d9f75844SAndroid Build Coastguard Worker if (content.rejected) {
1743*d9f75844SAndroid Build Coastguard Worker continue;
1744*d9f75844SAndroid Build Coastguard Worker }
1745*d9f75844SAndroid Build Coastguard Worker // TODO(deadbeef): There are conditions that make bundling two media
1746*d9f75844SAndroid Build Coastguard Worker // descriptions together illegal. For example, they use the same payload
1747*d9f75844SAndroid Build Coastguard Worker // type to represent different codecs, or same IDs for different header
1748*d9f75844SAndroid Build Coastguard Worker // extensions. We need to detect this and not try to bundle those media
1749*d9f75844SAndroid Build Coastguard Worker // descriptions together.
1750*d9f75844SAndroid Build Coastguard Worker offer_bundle.AddContentName(content.name);
1751*d9f75844SAndroid Build Coastguard Worker }
1752*d9f75844SAndroid Build Coastguard Worker if (!offer_bundle.content_names().empty()) {
1753*d9f75844SAndroid Build Coastguard Worker offer->AddGroup(offer_bundle);
1754*d9f75844SAndroid Build Coastguard Worker if (!UpdateTransportInfoForBundle(offer_bundle, offer.get())) {
1755*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR)
1756*d9f75844SAndroid Build Coastguard Worker << "CreateOffer failed to UpdateTransportInfoForBundle.";
1757*d9f75844SAndroid Build Coastguard Worker return nullptr;
1758*d9f75844SAndroid Build Coastguard Worker }
1759*d9f75844SAndroid Build Coastguard Worker if (!UpdateCryptoParamsForBundle(offer_bundle, offer.get())) {
1760*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR)
1761*d9f75844SAndroid Build Coastguard Worker << "CreateOffer failed to UpdateCryptoParamsForBundle.";
1762*d9f75844SAndroid Build Coastguard Worker return nullptr;
1763*d9f75844SAndroid Build Coastguard Worker }
1764*d9f75844SAndroid Build Coastguard Worker }
1765*d9f75844SAndroid Build Coastguard Worker }
1766*d9f75844SAndroid Build Coastguard Worker
1767*d9f75844SAndroid Build Coastguard Worker // The following determines how to signal MSIDs to ensure compatibility with
1768*d9f75844SAndroid Build Coastguard Worker // older endpoints (in particular, older Plan B endpoints).
1769*d9f75844SAndroid Build Coastguard Worker if (is_unified_plan_) {
1770*d9f75844SAndroid Build Coastguard Worker // Be conservative and signal using both a=msid and a=ssrc lines. Unified
1771*d9f75844SAndroid Build Coastguard Worker // Plan answerers will look at a=msid and Plan B answerers will look at the
1772*d9f75844SAndroid Build Coastguard Worker // a=ssrc MSID line.
1773*d9f75844SAndroid Build Coastguard Worker offer->set_msid_signaling(cricket::kMsidSignalingMediaSection |
1774*d9f75844SAndroid Build Coastguard Worker cricket::kMsidSignalingSsrcAttribute);
1775*d9f75844SAndroid Build Coastguard Worker } else {
1776*d9f75844SAndroid Build Coastguard Worker // Plan B always signals MSID using a=ssrc lines.
1777*d9f75844SAndroid Build Coastguard Worker offer->set_msid_signaling(cricket::kMsidSignalingSsrcAttribute);
1778*d9f75844SAndroid Build Coastguard Worker }
1779*d9f75844SAndroid Build Coastguard Worker
1780*d9f75844SAndroid Build Coastguard Worker offer->set_extmap_allow_mixed(session_options.offer_extmap_allow_mixed);
1781*d9f75844SAndroid Build Coastguard Worker
1782*d9f75844SAndroid Build Coastguard Worker return offer;
1783*d9f75844SAndroid Build Coastguard Worker }
1784*d9f75844SAndroid Build Coastguard Worker
1785*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<SessionDescription>
CreateAnswer(const SessionDescription * offer,const MediaSessionOptions & session_options,const SessionDescription * current_description) const1786*d9f75844SAndroid Build Coastguard Worker MediaSessionDescriptionFactory::CreateAnswer(
1787*d9f75844SAndroid Build Coastguard Worker const SessionDescription* offer,
1788*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
1789*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description) const {
1790*d9f75844SAndroid Build Coastguard Worker if (!offer) {
1791*d9f75844SAndroid Build Coastguard Worker return nullptr;
1792*d9f75844SAndroid Build Coastguard Worker }
1793*d9f75844SAndroid Build Coastguard Worker
1794*d9f75844SAndroid Build Coastguard Worker // Must have options for exactly as many sections as in the offer.
1795*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(offer->contents().size(),
1796*d9f75844SAndroid Build Coastguard Worker session_options.media_description_options.size());
1797*d9f75844SAndroid Build Coastguard Worker
1798*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator ice_credentials(
1799*d9f75844SAndroid Build Coastguard Worker session_options.pooled_ice_credentials);
1800*d9f75844SAndroid Build Coastguard Worker
1801*d9f75844SAndroid Build Coastguard Worker std::vector<const ContentInfo*> current_active_contents;
1802*d9f75844SAndroid Build Coastguard Worker if (current_description) {
1803*d9f75844SAndroid Build Coastguard Worker current_active_contents =
1804*d9f75844SAndroid Build Coastguard Worker GetActiveContents(*current_description, session_options);
1805*d9f75844SAndroid Build Coastguard Worker }
1806*d9f75844SAndroid Build Coastguard Worker
1807*d9f75844SAndroid Build Coastguard Worker StreamParamsVec current_streams =
1808*d9f75844SAndroid Build Coastguard Worker GetCurrentStreamParams(current_active_contents);
1809*d9f75844SAndroid Build Coastguard Worker
1810*d9f75844SAndroid Build Coastguard Worker // Get list of all possible codecs that respects existing payload type
1811*d9f75844SAndroid Build Coastguard Worker // mappings and uses a single payload type space.
1812*d9f75844SAndroid Build Coastguard Worker //
1813*d9f75844SAndroid Build Coastguard Worker // Note that these lists may be further filtered for each m= section; this
1814*d9f75844SAndroid Build Coastguard Worker // step is done just to establish the payload type mappings shared by all
1815*d9f75844SAndroid Build Coastguard Worker // sections.
1816*d9f75844SAndroid Build Coastguard Worker AudioCodecs answer_audio_codecs;
1817*d9f75844SAndroid Build Coastguard Worker VideoCodecs answer_video_codecs;
1818*d9f75844SAndroid Build Coastguard Worker GetCodecsForAnswer(current_active_contents, *offer, &answer_audio_codecs,
1819*d9f75844SAndroid Build Coastguard Worker &answer_video_codecs);
1820*d9f75844SAndroid Build Coastguard Worker
1821*d9f75844SAndroid Build Coastguard Worker auto answer = std::make_unique<SessionDescription>();
1822*d9f75844SAndroid Build Coastguard Worker
1823*d9f75844SAndroid Build Coastguard Worker // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE
1824*d9f75844SAndroid Build Coastguard Worker // group in the answer with the appropriate content names.
1825*d9f75844SAndroid Build Coastguard Worker std::vector<const ContentGroup*> offer_bundles =
1826*d9f75844SAndroid Build Coastguard Worker offer->GetGroupsByName(GROUP_TYPE_BUNDLE);
1827*d9f75844SAndroid Build Coastguard Worker // There are as many answer BUNDLE groups as offer BUNDLE groups (even if
1828*d9f75844SAndroid Build Coastguard Worker // rejected, we respond with an empty group). `offer_bundles`,
1829*d9f75844SAndroid Build Coastguard Worker // `answer_bundles` and `bundle_transports` share the same size and indices.
1830*d9f75844SAndroid Build Coastguard Worker std::vector<ContentGroup> answer_bundles;
1831*d9f75844SAndroid Build Coastguard Worker std::vector<std::unique_ptr<TransportInfo>> bundle_transports;
1832*d9f75844SAndroid Build Coastguard Worker answer_bundles.reserve(offer_bundles.size());
1833*d9f75844SAndroid Build Coastguard Worker bundle_transports.reserve(offer_bundles.size());
1834*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < offer_bundles.size(); ++i) {
1835*d9f75844SAndroid Build Coastguard Worker answer_bundles.emplace_back(GROUP_TYPE_BUNDLE);
1836*d9f75844SAndroid Build Coastguard Worker bundle_transports.emplace_back(nullptr);
1837*d9f75844SAndroid Build Coastguard Worker }
1838*d9f75844SAndroid Build Coastguard Worker
1839*d9f75844SAndroid Build Coastguard Worker answer->set_extmap_allow_mixed(offer->extmap_allow_mixed());
1840*d9f75844SAndroid Build Coastguard Worker
1841*d9f75844SAndroid Build Coastguard Worker // Iterate through the media description options, matching with existing
1842*d9f75844SAndroid Build Coastguard Worker // media descriptions in `current_description`.
1843*d9f75844SAndroid Build Coastguard Worker size_t msection_index = 0;
1844*d9f75844SAndroid Build Coastguard Worker for (const MediaDescriptionOptions& media_description_options :
1845*d9f75844SAndroid Build Coastguard Worker session_options.media_description_options) {
1846*d9f75844SAndroid Build Coastguard Worker const ContentInfo* offer_content = &offer->contents()[msection_index];
1847*d9f75844SAndroid Build Coastguard Worker // Media types and MIDs must match between the remote offer and the
1848*d9f75844SAndroid Build Coastguard Worker // MediaDescriptionOptions.
1849*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(
1850*d9f75844SAndroid Build Coastguard Worker IsMediaContentOfType(offer_content, media_description_options.type));
1851*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(media_description_options.mid == offer_content->name);
1852*d9f75844SAndroid Build Coastguard Worker // Get the index of the BUNDLE group that this MID belongs to, if any.
1853*d9f75844SAndroid Build Coastguard Worker absl::optional<size_t> bundle_index;
1854*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < offer_bundles.size(); ++i) {
1855*d9f75844SAndroid Build Coastguard Worker if (offer_bundles[i]->HasContentName(media_description_options.mid)) {
1856*d9f75844SAndroid Build Coastguard Worker bundle_index = i;
1857*d9f75844SAndroid Build Coastguard Worker break;
1858*d9f75844SAndroid Build Coastguard Worker }
1859*d9f75844SAndroid Build Coastguard Worker }
1860*d9f75844SAndroid Build Coastguard Worker TransportInfo* bundle_transport =
1861*d9f75844SAndroid Build Coastguard Worker bundle_index.has_value() ? bundle_transports[bundle_index.value()].get()
1862*d9f75844SAndroid Build Coastguard Worker : nullptr;
1863*d9f75844SAndroid Build Coastguard Worker
1864*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content = nullptr;
1865*d9f75844SAndroid Build Coastguard Worker if (current_description &&
1866*d9f75844SAndroid Build Coastguard Worker msection_index < current_description->contents().size()) {
1867*d9f75844SAndroid Build Coastguard Worker current_content = ¤t_description->contents()[msection_index];
1868*d9f75844SAndroid Build Coastguard Worker }
1869*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions header_extensions = RtpHeaderExtensionsFromCapabilities(
1870*d9f75844SAndroid Build Coastguard Worker UnstoppedRtpHeaderExtensionCapabilities(
1871*d9f75844SAndroid Build Coastguard Worker media_description_options.header_extensions));
1872*d9f75844SAndroid Build Coastguard Worker switch (media_description_options.type) {
1873*d9f75844SAndroid Build Coastguard Worker case MEDIA_TYPE_AUDIO:
1874*d9f75844SAndroid Build Coastguard Worker if (!AddAudioContentForAnswer(
1875*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options, offer_content,
1876*d9f75844SAndroid Build Coastguard Worker offer, current_content, current_description, bundle_transport,
1877*d9f75844SAndroid Build Coastguard Worker answer_audio_codecs, header_extensions, ¤t_streams,
1878*d9f75844SAndroid Build Coastguard Worker answer.get(), &ice_credentials)) {
1879*d9f75844SAndroid Build Coastguard Worker return nullptr;
1880*d9f75844SAndroid Build Coastguard Worker }
1881*d9f75844SAndroid Build Coastguard Worker break;
1882*d9f75844SAndroid Build Coastguard Worker case MEDIA_TYPE_VIDEO:
1883*d9f75844SAndroid Build Coastguard Worker if (!AddVideoContentForAnswer(
1884*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options, offer_content,
1885*d9f75844SAndroid Build Coastguard Worker offer, current_content, current_description, bundle_transport,
1886*d9f75844SAndroid Build Coastguard Worker answer_video_codecs, header_extensions, ¤t_streams,
1887*d9f75844SAndroid Build Coastguard Worker answer.get(), &ice_credentials)) {
1888*d9f75844SAndroid Build Coastguard Worker return nullptr;
1889*d9f75844SAndroid Build Coastguard Worker }
1890*d9f75844SAndroid Build Coastguard Worker break;
1891*d9f75844SAndroid Build Coastguard Worker case MEDIA_TYPE_DATA:
1892*d9f75844SAndroid Build Coastguard Worker if (!AddDataContentForAnswer(
1893*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options, offer_content,
1894*d9f75844SAndroid Build Coastguard Worker offer, current_content, current_description, bundle_transport,
1895*d9f75844SAndroid Build Coastguard Worker ¤t_streams, answer.get(), &ice_credentials)) {
1896*d9f75844SAndroid Build Coastguard Worker return nullptr;
1897*d9f75844SAndroid Build Coastguard Worker }
1898*d9f75844SAndroid Build Coastguard Worker break;
1899*d9f75844SAndroid Build Coastguard Worker case MEDIA_TYPE_UNSUPPORTED:
1900*d9f75844SAndroid Build Coastguard Worker if (!AddUnsupportedContentForAnswer(
1901*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options, offer_content,
1902*d9f75844SAndroid Build Coastguard Worker offer, current_content, current_description, bundle_transport,
1903*d9f75844SAndroid Build Coastguard Worker answer.get(), &ice_credentials)) {
1904*d9f75844SAndroid Build Coastguard Worker return nullptr;
1905*d9f75844SAndroid Build Coastguard Worker }
1906*d9f75844SAndroid Build Coastguard Worker break;
1907*d9f75844SAndroid Build Coastguard Worker default:
1908*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED();
1909*d9f75844SAndroid Build Coastguard Worker }
1910*d9f75844SAndroid Build Coastguard Worker ++msection_index;
1911*d9f75844SAndroid Build Coastguard Worker // See if we can add the newly generated m= section to the BUNDLE group in
1912*d9f75844SAndroid Build Coastguard Worker // the answer.
1913*d9f75844SAndroid Build Coastguard Worker ContentInfo& added = answer->contents().back();
1914*d9f75844SAndroid Build Coastguard Worker if (!added.rejected && session_options.bundle_enabled &&
1915*d9f75844SAndroid Build Coastguard Worker bundle_index.has_value()) {
1916*d9f75844SAndroid Build Coastguard Worker // The `bundle_index` is for `media_description_options.mid`.
1917*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_EQ(media_description_options.mid, added.name);
1918*d9f75844SAndroid Build Coastguard Worker answer_bundles[bundle_index.value()].AddContentName(added.name);
1919*d9f75844SAndroid Build Coastguard Worker bundle_transports[bundle_index.value()].reset(
1920*d9f75844SAndroid Build Coastguard Worker new TransportInfo(*answer->GetTransportInfoByName(added.name)));
1921*d9f75844SAndroid Build Coastguard Worker }
1922*d9f75844SAndroid Build Coastguard Worker }
1923*d9f75844SAndroid Build Coastguard Worker
1924*d9f75844SAndroid Build Coastguard Worker // If BUNDLE group(s) were offered, put the same number of BUNDLE groups in
1925*d9f75844SAndroid Build Coastguard Worker // the answer even if they're empty. RFC5888 says:
1926*d9f75844SAndroid Build Coastguard Worker //
1927*d9f75844SAndroid Build Coastguard Worker // A SIP entity that receives an offer that contains an "a=group" line
1928*d9f75844SAndroid Build Coastguard Worker // with semantics that are understood MUST return an answer that
1929*d9f75844SAndroid Build Coastguard Worker // contains an "a=group" line with the same semantics.
1930*d9f75844SAndroid Build Coastguard Worker if (!offer_bundles.empty()) {
1931*d9f75844SAndroid Build Coastguard Worker for (const ContentGroup& answer_bundle : answer_bundles) {
1932*d9f75844SAndroid Build Coastguard Worker answer->AddGroup(answer_bundle);
1933*d9f75844SAndroid Build Coastguard Worker
1934*d9f75844SAndroid Build Coastguard Worker if (answer_bundle.FirstContentName()) {
1935*d9f75844SAndroid Build Coastguard Worker // Share the same ICE credentials and crypto params across all contents,
1936*d9f75844SAndroid Build Coastguard Worker // as BUNDLE requires.
1937*d9f75844SAndroid Build Coastguard Worker if (!UpdateTransportInfoForBundle(answer_bundle, answer.get())) {
1938*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR)
1939*d9f75844SAndroid Build Coastguard Worker << "CreateAnswer failed to UpdateTransportInfoForBundle.";
1940*d9f75844SAndroid Build Coastguard Worker return NULL;
1941*d9f75844SAndroid Build Coastguard Worker }
1942*d9f75844SAndroid Build Coastguard Worker
1943*d9f75844SAndroid Build Coastguard Worker if (!UpdateCryptoParamsForBundle(answer_bundle, answer.get())) {
1944*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR)
1945*d9f75844SAndroid Build Coastguard Worker << "CreateAnswer failed to UpdateCryptoParamsForBundle.";
1946*d9f75844SAndroid Build Coastguard Worker return NULL;
1947*d9f75844SAndroid Build Coastguard Worker }
1948*d9f75844SAndroid Build Coastguard Worker }
1949*d9f75844SAndroid Build Coastguard Worker }
1950*d9f75844SAndroid Build Coastguard Worker }
1951*d9f75844SAndroid Build Coastguard Worker
1952*d9f75844SAndroid Build Coastguard Worker // The following determines how to signal MSIDs to ensure compatibility with
1953*d9f75844SAndroid Build Coastguard Worker // older endpoints (in particular, older Plan B endpoints).
1954*d9f75844SAndroid Build Coastguard Worker if (is_unified_plan_) {
1955*d9f75844SAndroid Build Coastguard Worker // Unified Plan needs to look at what the offer included to find the most
1956*d9f75844SAndroid Build Coastguard Worker // compatible answer.
1957*d9f75844SAndroid Build Coastguard Worker if (offer->msid_signaling() == 0) {
1958*d9f75844SAndroid Build Coastguard Worker // We end up here in one of three cases:
1959*d9f75844SAndroid Build Coastguard Worker // 1. An empty offer. We'll reply with an empty answer so it doesn't
1960*d9f75844SAndroid Build Coastguard Worker // matter what we pick here.
1961*d9f75844SAndroid Build Coastguard Worker // 2. A data channel only offer. We won't add any MSIDs to the answer so
1962*d9f75844SAndroid Build Coastguard Worker // it also doesn't matter what we pick here.
1963*d9f75844SAndroid Build Coastguard Worker // 3. Media that's either sendonly or inactive from the remote endpoint.
1964*d9f75844SAndroid Build Coastguard Worker // We don't have any information to say whether the endpoint is Plan B
1965*d9f75844SAndroid Build Coastguard Worker // or Unified Plan, so be conservative and send both.
1966*d9f75844SAndroid Build Coastguard Worker answer->set_msid_signaling(cricket::kMsidSignalingMediaSection |
1967*d9f75844SAndroid Build Coastguard Worker cricket::kMsidSignalingSsrcAttribute);
1968*d9f75844SAndroid Build Coastguard Worker } else if (offer->msid_signaling() ==
1969*d9f75844SAndroid Build Coastguard Worker (cricket::kMsidSignalingMediaSection |
1970*d9f75844SAndroid Build Coastguard Worker cricket::kMsidSignalingSsrcAttribute)) {
1971*d9f75844SAndroid Build Coastguard Worker // If both a=msid and a=ssrc MSID signaling methods were used, we're
1972*d9f75844SAndroid Build Coastguard Worker // probably talking to a Unified Plan endpoint so respond with just
1973*d9f75844SAndroid Build Coastguard Worker // a=msid.
1974*d9f75844SAndroid Build Coastguard Worker answer->set_msid_signaling(cricket::kMsidSignalingMediaSection);
1975*d9f75844SAndroid Build Coastguard Worker } else {
1976*d9f75844SAndroid Build Coastguard Worker // Otherwise, it's clear which method the offerer is using so repeat that
1977*d9f75844SAndroid Build Coastguard Worker // back to them.
1978*d9f75844SAndroid Build Coastguard Worker answer->set_msid_signaling(offer->msid_signaling());
1979*d9f75844SAndroid Build Coastguard Worker }
1980*d9f75844SAndroid Build Coastguard Worker } else {
1981*d9f75844SAndroid Build Coastguard Worker // Plan B always signals MSID using a=ssrc lines.
1982*d9f75844SAndroid Build Coastguard Worker answer->set_msid_signaling(cricket::kMsidSignalingSsrcAttribute);
1983*d9f75844SAndroid Build Coastguard Worker }
1984*d9f75844SAndroid Build Coastguard Worker
1985*d9f75844SAndroid Build Coastguard Worker return answer;
1986*d9f75844SAndroid Build Coastguard Worker }
1987*d9f75844SAndroid Build Coastguard Worker
GetAudioCodecsForOffer(const RtpTransceiverDirection & direction) const1988*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& MediaSessionDescriptionFactory::GetAudioCodecsForOffer(
1989*d9f75844SAndroid Build Coastguard Worker const RtpTransceiverDirection& direction) const {
1990*d9f75844SAndroid Build Coastguard Worker switch (direction) {
1991*d9f75844SAndroid Build Coastguard Worker // If stream is inactive - generate list as if sendrecv.
1992*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kSendRecv:
1993*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kStopped:
1994*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kInactive:
1995*d9f75844SAndroid Build Coastguard Worker return audio_sendrecv_codecs_;
1996*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kSendOnly:
1997*d9f75844SAndroid Build Coastguard Worker return audio_send_codecs_;
1998*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kRecvOnly:
1999*d9f75844SAndroid Build Coastguard Worker return audio_recv_codecs_;
2000*d9f75844SAndroid Build Coastguard Worker }
2001*d9f75844SAndroid Build Coastguard Worker RTC_CHECK_NOTREACHED();
2002*d9f75844SAndroid Build Coastguard Worker }
2003*d9f75844SAndroid Build Coastguard Worker
GetAudioCodecsForAnswer(const RtpTransceiverDirection & offer,const RtpTransceiverDirection & answer) const2004*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& MediaSessionDescriptionFactory::GetAudioCodecsForAnswer(
2005*d9f75844SAndroid Build Coastguard Worker const RtpTransceiverDirection& offer,
2006*d9f75844SAndroid Build Coastguard Worker const RtpTransceiverDirection& answer) const {
2007*d9f75844SAndroid Build Coastguard Worker switch (answer) {
2008*d9f75844SAndroid Build Coastguard Worker // For inactive and sendrecv answers, generate lists as if we were to accept
2009*d9f75844SAndroid Build Coastguard Worker // the offer's direction. See RFC 3264 Section 6.1.
2010*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kSendRecv:
2011*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kStopped:
2012*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kInactive:
2013*d9f75844SAndroid Build Coastguard Worker return GetAudioCodecsForOffer(
2014*d9f75844SAndroid Build Coastguard Worker webrtc::RtpTransceiverDirectionReversed(offer));
2015*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kSendOnly:
2016*d9f75844SAndroid Build Coastguard Worker return audio_send_codecs_;
2017*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kRecvOnly:
2018*d9f75844SAndroid Build Coastguard Worker return audio_recv_codecs_;
2019*d9f75844SAndroid Build Coastguard Worker }
2020*d9f75844SAndroid Build Coastguard Worker RTC_CHECK_NOTREACHED();
2021*d9f75844SAndroid Build Coastguard Worker }
2022*d9f75844SAndroid Build Coastguard Worker
GetVideoCodecsForOffer(const RtpTransceiverDirection & direction) const2023*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& MediaSessionDescriptionFactory::GetVideoCodecsForOffer(
2024*d9f75844SAndroid Build Coastguard Worker const RtpTransceiverDirection& direction) const {
2025*d9f75844SAndroid Build Coastguard Worker switch (direction) {
2026*d9f75844SAndroid Build Coastguard Worker // If stream is inactive - generate list as if sendrecv.
2027*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kSendRecv:
2028*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kStopped:
2029*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kInactive:
2030*d9f75844SAndroid Build Coastguard Worker return video_sendrecv_codecs_;
2031*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kSendOnly:
2032*d9f75844SAndroid Build Coastguard Worker return video_send_codecs_;
2033*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kRecvOnly:
2034*d9f75844SAndroid Build Coastguard Worker return video_recv_codecs_;
2035*d9f75844SAndroid Build Coastguard Worker }
2036*d9f75844SAndroid Build Coastguard Worker RTC_CHECK_NOTREACHED();
2037*d9f75844SAndroid Build Coastguard Worker }
2038*d9f75844SAndroid Build Coastguard Worker
GetVideoCodecsForAnswer(const RtpTransceiverDirection & offer,const RtpTransceiverDirection & answer) const2039*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& MediaSessionDescriptionFactory::GetVideoCodecsForAnswer(
2040*d9f75844SAndroid Build Coastguard Worker const RtpTransceiverDirection& offer,
2041*d9f75844SAndroid Build Coastguard Worker const RtpTransceiverDirection& answer) const {
2042*d9f75844SAndroid Build Coastguard Worker switch (answer) {
2043*d9f75844SAndroid Build Coastguard Worker // For inactive and sendrecv answers, generate lists as if we were to accept
2044*d9f75844SAndroid Build Coastguard Worker // the offer's direction. See RFC 3264 Section 6.1.
2045*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kSendRecv:
2046*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kStopped:
2047*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kInactive:
2048*d9f75844SAndroid Build Coastguard Worker return GetVideoCodecsForOffer(
2049*d9f75844SAndroid Build Coastguard Worker webrtc::RtpTransceiverDirectionReversed(offer));
2050*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kSendOnly:
2051*d9f75844SAndroid Build Coastguard Worker return video_send_codecs_;
2052*d9f75844SAndroid Build Coastguard Worker case RtpTransceiverDirection::kRecvOnly:
2053*d9f75844SAndroid Build Coastguard Worker return video_recv_codecs_;
2054*d9f75844SAndroid Build Coastguard Worker }
2055*d9f75844SAndroid Build Coastguard Worker RTC_CHECK_NOTREACHED();
2056*d9f75844SAndroid Build Coastguard Worker }
2057*d9f75844SAndroid Build Coastguard Worker
MergeCodecsFromDescription(const std::vector<const ContentInfo * > & current_active_contents,AudioCodecs * audio_codecs,VideoCodecs * video_codecs,UsedPayloadTypes * used_pltypes,const webrtc::FieldTrialsView * field_trials)2058*d9f75844SAndroid Build Coastguard Worker void MergeCodecsFromDescription(
2059*d9f75844SAndroid Build Coastguard Worker const std::vector<const ContentInfo*>& current_active_contents,
2060*d9f75844SAndroid Build Coastguard Worker AudioCodecs* audio_codecs,
2061*d9f75844SAndroid Build Coastguard Worker VideoCodecs* video_codecs,
2062*d9f75844SAndroid Build Coastguard Worker UsedPayloadTypes* used_pltypes,
2063*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials) {
2064*d9f75844SAndroid Build Coastguard Worker for (const ContentInfo* content : current_active_contents) {
2065*d9f75844SAndroid Build Coastguard Worker if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) {
2066*d9f75844SAndroid Build Coastguard Worker const AudioContentDescription* audio =
2067*d9f75844SAndroid Build Coastguard Worker content->media_description()->as_audio();
2068*d9f75844SAndroid Build Coastguard Worker MergeCodecs<AudioCodec>(audio->codecs(), audio_codecs, used_pltypes,
2069*d9f75844SAndroid Build Coastguard Worker field_trials);
2070*d9f75844SAndroid Build Coastguard Worker } else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) {
2071*d9f75844SAndroid Build Coastguard Worker const VideoContentDescription* video =
2072*d9f75844SAndroid Build Coastguard Worker content->media_description()->as_video();
2073*d9f75844SAndroid Build Coastguard Worker MergeCodecs<VideoCodec>(video->codecs(), video_codecs, used_pltypes,
2074*d9f75844SAndroid Build Coastguard Worker field_trials);
2075*d9f75844SAndroid Build Coastguard Worker }
2076*d9f75844SAndroid Build Coastguard Worker }
2077*d9f75844SAndroid Build Coastguard Worker }
2078*d9f75844SAndroid Build Coastguard Worker
2079*d9f75844SAndroid Build Coastguard Worker // Getting codecs for an offer involves these steps:
2080*d9f75844SAndroid Build Coastguard Worker //
2081*d9f75844SAndroid Build Coastguard Worker // 1. Construct payload type -> codec mappings for current description.
2082*d9f75844SAndroid Build Coastguard Worker // 2. Add any reference codecs that weren't already present
2083*d9f75844SAndroid Build Coastguard Worker // 3. For each individual media description (m= section), filter codecs based
2084*d9f75844SAndroid Build Coastguard Worker // on the directional attribute (happens in another method).
GetCodecsForOffer(const std::vector<const ContentInfo * > & current_active_contents,AudioCodecs * audio_codecs,VideoCodecs * video_codecs) const2085*d9f75844SAndroid Build Coastguard Worker void MediaSessionDescriptionFactory::GetCodecsForOffer(
2086*d9f75844SAndroid Build Coastguard Worker const std::vector<const ContentInfo*>& current_active_contents,
2087*d9f75844SAndroid Build Coastguard Worker AudioCodecs* audio_codecs,
2088*d9f75844SAndroid Build Coastguard Worker VideoCodecs* video_codecs) const {
2089*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials =
2090*d9f75844SAndroid Build Coastguard Worker &transport_desc_factory_->trials();
2091*d9f75844SAndroid Build Coastguard Worker // First - get all codecs from the current description if the media type
2092*d9f75844SAndroid Build Coastguard Worker // is used. Add them to `used_pltypes` so the payload type is not reused if a
2093*d9f75844SAndroid Build Coastguard Worker // new media type is added.
2094*d9f75844SAndroid Build Coastguard Worker UsedPayloadTypes used_pltypes;
2095*d9f75844SAndroid Build Coastguard Worker MergeCodecsFromDescription(current_active_contents, audio_codecs,
2096*d9f75844SAndroid Build Coastguard Worker video_codecs, &used_pltypes, field_trials);
2097*d9f75844SAndroid Build Coastguard Worker
2098*d9f75844SAndroid Build Coastguard Worker // Add our codecs that are not in the current description.
2099*d9f75844SAndroid Build Coastguard Worker MergeCodecs<AudioCodec>(all_audio_codecs_, audio_codecs, &used_pltypes,
2100*d9f75844SAndroid Build Coastguard Worker field_trials);
2101*d9f75844SAndroid Build Coastguard Worker MergeCodecs<VideoCodec>(all_video_codecs_, video_codecs, &used_pltypes,
2102*d9f75844SAndroid Build Coastguard Worker field_trials);
2103*d9f75844SAndroid Build Coastguard Worker }
2104*d9f75844SAndroid Build Coastguard Worker
2105*d9f75844SAndroid Build Coastguard Worker // Getting codecs for an answer involves these steps:
2106*d9f75844SAndroid Build Coastguard Worker //
2107*d9f75844SAndroid Build Coastguard Worker // 1. Construct payload type -> codec mappings for current description.
2108*d9f75844SAndroid Build Coastguard Worker // 2. Add any codecs from the offer that weren't already present.
2109*d9f75844SAndroid Build Coastguard Worker // 3. Add any remaining codecs that weren't already present.
2110*d9f75844SAndroid Build Coastguard Worker // 4. For each individual media description (m= section), filter codecs based
2111*d9f75844SAndroid Build Coastguard Worker // on the directional attribute (happens in another method).
GetCodecsForAnswer(const std::vector<const ContentInfo * > & current_active_contents,const SessionDescription & remote_offer,AudioCodecs * audio_codecs,VideoCodecs * video_codecs) const2112*d9f75844SAndroid Build Coastguard Worker void MediaSessionDescriptionFactory::GetCodecsForAnswer(
2113*d9f75844SAndroid Build Coastguard Worker const std::vector<const ContentInfo*>& current_active_contents,
2114*d9f75844SAndroid Build Coastguard Worker const SessionDescription& remote_offer,
2115*d9f75844SAndroid Build Coastguard Worker AudioCodecs* audio_codecs,
2116*d9f75844SAndroid Build Coastguard Worker VideoCodecs* video_codecs) const {
2117*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials =
2118*d9f75844SAndroid Build Coastguard Worker &transport_desc_factory_->trials();
2119*d9f75844SAndroid Build Coastguard Worker // First - get all codecs from the current description if the media type
2120*d9f75844SAndroid Build Coastguard Worker // is used. Add them to `used_pltypes` so the payload type is not reused if a
2121*d9f75844SAndroid Build Coastguard Worker // new media type is added.
2122*d9f75844SAndroid Build Coastguard Worker UsedPayloadTypes used_pltypes;
2123*d9f75844SAndroid Build Coastguard Worker MergeCodecsFromDescription(current_active_contents, audio_codecs,
2124*d9f75844SAndroid Build Coastguard Worker video_codecs, &used_pltypes, field_trials);
2125*d9f75844SAndroid Build Coastguard Worker
2126*d9f75844SAndroid Build Coastguard Worker // Second - filter out codecs that we don't support at all and should ignore.
2127*d9f75844SAndroid Build Coastguard Worker AudioCodecs filtered_offered_audio_codecs;
2128*d9f75844SAndroid Build Coastguard Worker VideoCodecs filtered_offered_video_codecs;
2129*d9f75844SAndroid Build Coastguard Worker for (const ContentInfo& content : remote_offer.contents()) {
2130*d9f75844SAndroid Build Coastguard Worker if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
2131*d9f75844SAndroid Build Coastguard Worker const AudioContentDescription* audio =
2132*d9f75844SAndroid Build Coastguard Worker content.media_description()->as_audio();
2133*d9f75844SAndroid Build Coastguard Worker for (const AudioCodec& offered_audio_codec : audio->codecs()) {
2134*d9f75844SAndroid Build Coastguard Worker if (!FindMatchingCodec<AudioCodec>(
2135*d9f75844SAndroid Build Coastguard Worker audio->codecs(), filtered_offered_audio_codecs,
2136*d9f75844SAndroid Build Coastguard Worker offered_audio_codec, nullptr, field_trials) &&
2137*d9f75844SAndroid Build Coastguard Worker FindMatchingCodec<AudioCodec>(audio->codecs(), all_audio_codecs_,
2138*d9f75844SAndroid Build Coastguard Worker offered_audio_codec, nullptr,
2139*d9f75844SAndroid Build Coastguard Worker field_trials)) {
2140*d9f75844SAndroid Build Coastguard Worker filtered_offered_audio_codecs.push_back(offered_audio_codec);
2141*d9f75844SAndroid Build Coastguard Worker }
2142*d9f75844SAndroid Build Coastguard Worker }
2143*d9f75844SAndroid Build Coastguard Worker } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
2144*d9f75844SAndroid Build Coastguard Worker const VideoContentDescription* video =
2145*d9f75844SAndroid Build Coastguard Worker content.media_description()->as_video();
2146*d9f75844SAndroid Build Coastguard Worker for (const VideoCodec& offered_video_codec : video->codecs()) {
2147*d9f75844SAndroid Build Coastguard Worker if (!FindMatchingCodec<VideoCodec>(
2148*d9f75844SAndroid Build Coastguard Worker video->codecs(), filtered_offered_video_codecs,
2149*d9f75844SAndroid Build Coastguard Worker offered_video_codec, nullptr, field_trials) &&
2150*d9f75844SAndroid Build Coastguard Worker FindMatchingCodec<VideoCodec>(video->codecs(), all_video_codecs_,
2151*d9f75844SAndroid Build Coastguard Worker offered_video_codec, nullptr,
2152*d9f75844SAndroid Build Coastguard Worker field_trials)) {
2153*d9f75844SAndroid Build Coastguard Worker filtered_offered_video_codecs.push_back(offered_video_codec);
2154*d9f75844SAndroid Build Coastguard Worker }
2155*d9f75844SAndroid Build Coastguard Worker }
2156*d9f75844SAndroid Build Coastguard Worker }
2157*d9f75844SAndroid Build Coastguard Worker }
2158*d9f75844SAndroid Build Coastguard Worker
2159*d9f75844SAndroid Build Coastguard Worker // Add codecs that are not in the current description but were in
2160*d9f75844SAndroid Build Coastguard Worker // `remote_offer`.
2161*d9f75844SAndroid Build Coastguard Worker MergeCodecs<AudioCodec>(filtered_offered_audio_codecs, audio_codecs,
2162*d9f75844SAndroid Build Coastguard Worker &used_pltypes, field_trials);
2163*d9f75844SAndroid Build Coastguard Worker MergeCodecs<VideoCodec>(filtered_offered_video_codecs, video_codecs,
2164*d9f75844SAndroid Build Coastguard Worker &used_pltypes, field_trials);
2165*d9f75844SAndroid Build Coastguard Worker }
2166*d9f75844SAndroid Build Coastguard Worker
2167*d9f75844SAndroid Build Coastguard Worker MediaSessionDescriptionFactory::AudioVideoRtpHeaderExtensions
GetOfferedRtpHeaderExtensionsWithIds(const std::vector<const ContentInfo * > & current_active_contents,bool extmap_allow_mixed,const std::vector<MediaDescriptionOptions> & media_description_options) const2168*d9f75844SAndroid Build Coastguard Worker MediaSessionDescriptionFactory::GetOfferedRtpHeaderExtensionsWithIds(
2169*d9f75844SAndroid Build Coastguard Worker const std::vector<const ContentInfo*>& current_active_contents,
2170*d9f75844SAndroid Build Coastguard Worker bool extmap_allow_mixed,
2171*d9f75844SAndroid Build Coastguard Worker const std::vector<MediaDescriptionOptions>& media_description_options)
2172*d9f75844SAndroid Build Coastguard Worker const {
2173*d9f75844SAndroid Build Coastguard Worker // All header extensions allocated from the same range to avoid potential
2174*d9f75844SAndroid Build Coastguard Worker // issues when using BUNDLE.
2175*d9f75844SAndroid Build Coastguard Worker
2176*d9f75844SAndroid Build Coastguard Worker // Strictly speaking the SDP attribute extmap_allow_mixed signals that the
2177*d9f75844SAndroid Build Coastguard Worker // receiver supports an RTP stream where one- and two-byte RTP header
2178*d9f75844SAndroid Build Coastguard Worker // extensions are mixed. For backwards compatibility reasons it's used in
2179*d9f75844SAndroid Build Coastguard Worker // WebRTC to signal that two-byte RTP header extensions are supported.
2180*d9f75844SAndroid Build Coastguard Worker UsedRtpHeaderExtensionIds used_ids(
2181*d9f75844SAndroid Build Coastguard Worker extmap_allow_mixed ? UsedRtpHeaderExtensionIds::IdDomain::kTwoByteAllowed
2182*d9f75844SAndroid Build Coastguard Worker : UsedRtpHeaderExtensionIds::IdDomain::kOneByteOnly);
2183*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions all_regular_extensions;
2184*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions all_encrypted_extensions;
2185*d9f75844SAndroid Build Coastguard Worker
2186*d9f75844SAndroid Build Coastguard Worker AudioVideoRtpHeaderExtensions offered_extensions;
2187*d9f75844SAndroid Build Coastguard Worker // First - get all extensions from the current description if the media type
2188*d9f75844SAndroid Build Coastguard Worker // is used.
2189*d9f75844SAndroid Build Coastguard Worker // Add them to `used_ids` so the local ids are not reused if a new media
2190*d9f75844SAndroid Build Coastguard Worker // type is added.
2191*d9f75844SAndroid Build Coastguard Worker for (const ContentInfo* content : current_active_contents) {
2192*d9f75844SAndroid Build Coastguard Worker if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) {
2193*d9f75844SAndroid Build Coastguard Worker const AudioContentDescription* audio =
2194*d9f75844SAndroid Build Coastguard Worker content->media_description()->as_audio();
2195*d9f75844SAndroid Build Coastguard Worker MergeRtpHdrExts(audio->rtp_header_extensions(), &offered_extensions.audio,
2196*d9f75844SAndroid Build Coastguard Worker &all_regular_extensions, &all_encrypted_extensions,
2197*d9f75844SAndroid Build Coastguard Worker &used_ids);
2198*d9f75844SAndroid Build Coastguard Worker } else if (IsMediaContentOfType(content, MEDIA_TYPE_VIDEO)) {
2199*d9f75844SAndroid Build Coastguard Worker const VideoContentDescription* video =
2200*d9f75844SAndroid Build Coastguard Worker content->media_description()->as_video();
2201*d9f75844SAndroid Build Coastguard Worker MergeRtpHdrExts(video->rtp_header_extensions(), &offered_extensions.video,
2202*d9f75844SAndroid Build Coastguard Worker &all_regular_extensions, &all_encrypted_extensions,
2203*d9f75844SAndroid Build Coastguard Worker &used_ids);
2204*d9f75844SAndroid Build Coastguard Worker }
2205*d9f75844SAndroid Build Coastguard Worker }
2206*d9f75844SAndroid Build Coastguard Worker
2207*d9f75844SAndroid Build Coastguard Worker // Add all encountered header extensions in the media description options that
2208*d9f75844SAndroid Build Coastguard Worker // are not in the current description.
2209*d9f75844SAndroid Build Coastguard Worker
2210*d9f75844SAndroid Build Coastguard Worker for (const auto& entry : media_description_options) {
2211*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensions filtered_extensions =
2212*d9f75844SAndroid Build Coastguard Worker filtered_rtp_header_extensions(UnstoppedOrPresentRtpHeaderExtensions(
2213*d9f75844SAndroid Build Coastguard Worker entry.header_extensions, all_regular_extensions,
2214*d9f75844SAndroid Build Coastguard Worker all_encrypted_extensions));
2215*d9f75844SAndroid Build Coastguard Worker if (entry.type == MEDIA_TYPE_AUDIO)
2216*d9f75844SAndroid Build Coastguard Worker MergeRtpHdrExts(filtered_extensions, &offered_extensions.audio,
2217*d9f75844SAndroid Build Coastguard Worker &all_regular_extensions, &all_encrypted_extensions,
2218*d9f75844SAndroid Build Coastguard Worker &used_ids);
2219*d9f75844SAndroid Build Coastguard Worker else if (entry.type == MEDIA_TYPE_VIDEO)
2220*d9f75844SAndroid Build Coastguard Worker MergeRtpHdrExts(filtered_extensions, &offered_extensions.video,
2221*d9f75844SAndroid Build Coastguard Worker &all_regular_extensions, &all_encrypted_extensions,
2222*d9f75844SAndroid Build Coastguard Worker &used_ids);
2223*d9f75844SAndroid Build Coastguard Worker }
2224*d9f75844SAndroid Build Coastguard Worker // TODO(jbauch): Support adding encrypted header extensions to existing
2225*d9f75844SAndroid Build Coastguard Worker // sessions.
2226*d9f75844SAndroid Build Coastguard Worker if (enable_encrypted_rtp_header_extensions_ &&
2227*d9f75844SAndroid Build Coastguard Worker current_active_contents.empty()) {
2228*d9f75844SAndroid Build Coastguard Worker AddEncryptedVersionsOfHdrExts(&offered_extensions.audio,
2229*d9f75844SAndroid Build Coastguard Worker &all_encrypted_extensions, &used_ids);
2230*d9f75844SAndroid Build Coastguard Worker AddEncryptedVersionsOfHdrExts(&offered_extensions.video,
2231*d9f75844SAndroid Build Coastguard Worker &all_encrypted_extensions, &used_ids);
2232*d9f75844SAndroid Build Coastguard Worker }
2233*d9f75844SAndroid Build Coastguard Worker return offered_extensions;
2234*d9f75844SAndroid Build Coastguard Worker }
2235*d9f75844SAndroid Build Coastguard Worker
AddTransportOffer(const std::string & content_name,const TransportOptions & transport_options,const SessionDescription * current_desc,SessionDescription * offer_desc,IceCredentialsIterator * ice_credentials) const2236*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddTransportOffer(
2237*d9f75844SAndroid Build Coastguard Worker const std::string& content_name,
2238*d9f75844SAndroid Build Coastguard Worker const TransportOptions& transport_options,
2239*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_desc,
2240*d9f75844SAndroid Build Coastguard Worker SessionDescription* offer_desc,
2241*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2242*d9f75844SAndroid Build Coastguard Worker if (!transport_desc_factory_)
2243*d9f75844SAndroid Build Coastguard Worker return false;
2244*d9f75844SAndroid Build Coastguard Worker const TransportDescription* current_tdesc =
2245*d9f75844SAndroid Build Coastguard Worker GetTransportDescription(content_name, current_desc);
2246*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TransportDescription> new_tdesc(
2247*d9f75844SAndroid Build Coastguard Worker transport_desc_factory_->CreateOffer(transport_options, current_tdesc,
2248*d9f75844SAndroid Build Coastguard Worker ice_credentials));
2249*d9f75844SAndroid Build Coastguard Worker if (!new_tdesc) {
2250*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_ERROR) << "Failed to AddTransportOffer, content name="
2251*d9f75844SAndroid Build Coastguard Worker << content_name;
2252*d9f75844SAndroid Build Coastguard Worker }
2253*d9f75844SAndroid Build Coastguard Worker offer_desc->AddTransportInfo(TransportInfo(content_name, *new_tdesc));
2254*d9f75844SAndroid Build Coastguard Worker return true;
2255*d9f75844SAndroid Build Coastguard Worker }
2256*d9f75844SAndroid Build Coastguard Worker
2257*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TransportDescription>
CreateTransportAnswer(const std::string & content_name,const SessionDescription * offer_desc,const TransportOptions & transport_options,const SessionDescription * current_desc,bool require_transport_attributes,IceCredentialsIterator * ice_credentials) const2258*d9f75844SAndroid Build Coastguard Worker MediaSessionDescriptionFactory::CreateTransportAnswer(
2259*d9f75844SAndroid Build Coastguard Worker const std::string& content_name,
2260*d9f75844SAndroid Build Coastguard Worker const SessionDescription* offer_desc,
2261*d9f75844SAndroid Build Coastguard Worker const TransportOptions& transport_options,
2262*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_desc,
2263*d9f75844SAndroid Build Coastguard Worker bool require_transport_attributes,
2264*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2265*d9f75844SAndroid Build Coastguard Worker if (!transport_desc_factory_)
2266*d9f75844SAndroid Build Coastguard Worker return NULL;
2267*d9f75844SAndroid Build Coastguard Worker const TransportDescription* offer_tdesc =
2268*d9f75844SAndroid Build Coastguard Worker GetTransportDescription(content_name, offer_desc);
2269*d9f75844SAndroid Build Coastguard Worker const TransportDescription* current_tdesc =
2270*d9f75844SAndroid Build Coastguard Worker GetTransportDescription(content_name, current_desc);
2271*d9f75844SAndroid Build Coastguard Worker return transport_desc_factory_->CreateAnswer(offer_tdesc, transport_options,
2272*d9f75844SAndroid Build Coastguard Worker require_transport_attributes,
2273*d9f75844SAndroid Build Coastguard Worker current_tdesc, ice_credentials);
2274*d9f75844SAndroid Build Coastguard Worker }
2275*d9f75844SAndroid Build Coastguard Worker
AddTransportAnswer(const std::string & content_name,const TransportDescription & transport_desc,SessionDescription * answer_desc) const2276*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddTransportAnswer(
2277*d9f75844SAndroid Build Coastguard Worker const std::string& content_name,
2278*d9f75844SAndroid Build Coastguard Worker const TransportDescription& transport_desc,
2279*d9f75844SAndroid Build Coastguard Worker SessionDescription* answer_desc) const {
2280*d9f75844SAndroid Build Coastguard Worker answer_desc->AddTransportInfo(TransportInfo(content_name, transport_desc));
2281*d9f75844SAndroid Build Coastguard Worker return true;
2282*d9f75844SAndroid Build Coastguard Worker }
2283*d9f75844SAndroid Build Coastguard Worker
2284*d9f75844SAndroid Build Coastguard Worker // `audio_codecs` = set of all possible codecs that can be used, with correct
2285*d9f75844SAndroid Build Coastguard Worker // payload type mappings
2286*d9f75844SAndroid Build Coastguard Worker //
2287*d9f75844SAndroid Build Coastguard Worker // `supported_audio_codecs` = set of codecs that are supported for the direction
2288*d9f75844SAndroid Build Coastguard Worker // of this m= section
2289*d9f75844SAndroid Build Coastguard Worker //
2290*d9f75844SAndroid Build Coastguard Worker // acd->codecs() = set of previously negotiated codecs for this m= section
2291*d9f75844SAndroid Build Coastguard Worker //
2292*d9f75844SAndroid Build Coastguard Worker // The payload types should come from audio_codecs, but the order should come
2293*d9f75844SAndroid Build Coastguard Worker // from acd->codecs() and then supported_codecs, to ensure that re-offers don't
2294*d9f75844SAndroid Build Coastguard Worker // change existing codec priority, and that new codecs are added with the right
2295*d9f75844SAndroid Build Coastguard Worker // priority.
AddAudioContentForOffer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const ContentInfo * current_content,const SessionDescription * current_description,const RtpHeaderExtensions & audio_rtp_extensions,const AudioCodecs & audio_codecs,StreamParamsVec * current_streams,SessionDescription * desc,IceCredentialsIterator * ice_credentials) const2296*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddAudioContentForOffer(
2297*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
2298*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
2299*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content,
2300*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description,
2301*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& audio_rtp_extensions,
2302*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& audio_codecs,
2303*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
2304*d9f75844SAndroid Build Coastguard Worker SessionDescription* desc,
2305*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2306*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials =
2307*d9f75844SAndroid Build Coastguard Worker &transport_desc_factory_->trials();
2308*d9f75844SAndroid Build Coastguard Worker // Filter audio_codecs (which includes all codecs, with correctly remapped
2309*d9f75844SAndroid Build Coastguard Worker // payload types) based on transceiver direction.
2310*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& supported_audio_codecs =
2311*d9f75844SAndroid Build Coastguard Worker GetAudioCodecsForOffer(media_description_options.direction);
2312*d9f75844SAndroid Build Coastguard Worker
2313*d9f75844SAndroid Build Coastguard Worker AudioCodecs filtered_codecs;
2314*d9f75844SAndroid Build Coastguard Worker
2315*d9f75844SAndroid Build Coastguard Worker if (!media_description_options.codec_preferences.empty()) {
2316*d9f75844SAndroid Build Coastguard Worker // Add the codecs from the current transceiver's codec preferences.
2317*d9f75844SAndroid Build Coastguard Worker // They override any existing codecs from previous negotiations.
2318*d9f75844SAndroid Build Coastguard Worker filtered_codecs = MatchCodecPreference(
2319*d9f75844SAndroid Build Coastguard Worker media_description_options.codec_preferences, audio_codecs,
2320*d9f75844SAndroid Build Coastguard Worker supported_audio_codecs, field_trials);
2321*d9f75844SAndroid Build Coastguard Worker } else {
2322*d9f75844SAndroid Build Coastguard Worker // Add the codecs from current content if it exists and is not rejected nor
2323*d9f75844SAndroid Build Coastguard Worker // recycled.
2324*d9f75844SAndroid Build Coastguard Worker if (current_content && !current_content->rejected &&
2325*d9f75844SAndroid Build Coastguard Worker current_content->name == media_description_options.mid) {
2326*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_AUDIO));
2327*d9f75844SAndroid Build Coastguard Worker const AudioContentDescription* acd =
2328*d9f75844SAndroid Build Coastguard Worker current_content->media_description()->as_audio();
2329*d9f75844SAndroid Build Coastguard Worker for (const AudioCodec& codec : acd->codecs()) {
2330*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<AudioCodec>(acd->codecs(), audio_codecs, codec,
2331*d9f75844SAndroid Build Coastguard Worker nullptr, field_trials)) {
2332*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(codec);
2333*d9f75844SAndroid Build Coastguard Worker }
2334*d9f75844SAndroid Build Coastguard Worker }
2335*d9f75844SAndroid Build Coastguard Worker }
2336*d9f75844SAndroid Build Coastguard Worker // Add other supported audio codecs.
2337*d9f75844SAndroid Build Coastguard Worker AudioCodec found_codec;
2338*d9f75844SAndroid Build Coastguard Worker for (const AudioCodec& codec : supported_audio_codecs) {
2339*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
2340*d9f75844SAndroid Build Coastguard Worker codec, &found_codec, field_trials) &&
2341*d9f75844SAndroid Build Coastguard Worker !FindMatchingCodec<AudioCodec>(supported_audio_codecs,
2342*d9f75844SAndroid Build Coastguard Worker filtered_codecs, codec, nullptr,
2343*d9f75844SAndroid Build Coastguard Worker field_trials)) {
2344*d9f75844SAndroid Build Coastguard Worker // Use the `found_codec` from `audio_codecs` because it has the
2345*d9f75844SAndroid Build Coastguard Worker // correctly mapped payload type.
2346*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(found_codec);
2347*d9f75844SAndroid Build Coastguard Worker }
2348*d9f75844SAndroid Build Coastguard Worker }
2349*d9f75844SAndroid Build Coastguard Worker }
2350*d9f75844SAndroid Build Coastguard Worker if (!session_options.vad_enabled) {
2351*d9f75844SAndroid Build Coastguard Worker // If application doesn't want CN codecs in offer.
2352*d9f75844SAndroid Build Coastguard Worker StripCNCodecs(&filtered_codecs);
2353*d9f75844SAndroid Build Coastguard Worker }
2354*d9f75844SAndroid Build Coastguard Worker
2355*d9f75844SAndroid Build Coastguard Worker cricket::SecurePolicy sdes_policy =
2356*d9f75844SAndroid Build Coastguard Worker IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
2357*d9f75844SAndroid Build Coastguard Worker : secure();
2358*d9f75844SAndroid Build Coastguard Worker
2359*d9f75844SAndroid Build Coastguard Worker auto audio = std::make_unique<AudioContentDescription>();
2360*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> crypto_suites;
2361*d9f75844SAndroid Build Coastguard Worker GetSupportedAudioSdesCryptoSuiteNames(session_options.crypto_options,
2362*d9f75844SAndroid Build Coastguard Worker &crypto_suites);
2363*d9f75844SAndroid Build Coastguard Worker if (!CreateMediaContentOffer(
2364*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options, filtered_codecs,
2365*d9f75844SAndroid Build Coastguard Worker sdes_policy, GetCryptos(current_content), crypto_suites,
2366*d9f75844SAndroid Build Coastguard Worker audio_rtp_extensions, ssrc_generator(), current_streams, audio.get(),
2367*d9f75844SAndroid Build Coastguard Worker transport_desc_factory_->trials())) {
2368*d9f75844SAndroid Build Coastguard Worker return false;
2369*d9f75844SAndroid Build Coastguard Worker }
2370*d9f75844SAndroid Build Coastguard Worker
2371*d9f75844SAndroid Build Coastguard Worker bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
2372*d9f75844SAndroid Build Coastguard Worker SetMediaProtocol(secure_transport, audio.get());
2373*d9f75844SAndroid Build Coastguard Worker
2374*d9f75844SAndroid Build Coastguard Worker audio->set_direction(media_description_options.direction);
2375*d9f75844SAndroid Build Coastguard Worker
2376*d9f75844SAndroid Build Coastguard Worker desc->AddContent(media_description_options.mid, MediaProtocolType::kRtp,
2377*d9f75844SAndroid Build Coastguard Worker media_description_options.stopped, std::move(audio));
2378*d9f75844SAndroid Build Coastguard Worker if (!AddTransportOffer(media_description_options.mid,
2379*d9f75844SAndroid Build Coastguard Worker media_description_options.transport_options,
2380*d9f75844SAndroid Build Coastguard Worker current_description, desc, ice_credentials)) {
2381*d9f75844SAndroid Build Coastguard Worker return false;
2382*d9f75844SAndroid Build Coastguard Worker }
2383*d9f75844SAndroid Build Coastguard Worker
2384*d9f75844SAndroid Build Coastguard Worker return true;
2385*d9f75844SAndroid Build Coastguard Worker }
2386*d9f75844SAndroid Build Coastguard Worker
2387*d9f75844SAndroid Build Coastguard Worker // TODO(kron): This function is very similar to AddAudioContentForOffer.
2388*d9f75844SAndroid Build Coastguard Worker // Refactor to reuse shared code.
AddVideoContentForOffer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const ContentInfo * current_content,const SessionDescription * current_description,const RtpHeaderExtensions & video_rtp_extensions,const VideoCodecs & video_codecs,StreamParamsVec * current_streams,SessionDescription * desc,IceCredentialsIterator * ice_credentials) const2389*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddVideoContentForOffer(
2390*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
2391*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
2392*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content,
2393*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description,
2394*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& video_rtp_extensions,
2395*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& video_codecs,
2396*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
2397*d9f75844SAndroid Build Coastguard Worker SessionDescription* desc,
2398*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2399*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials =
2400*d9f75844SAndroid Build Coastguard Worker &transport_desc_factory_->trials();
2401*d9f75844SAndroid Build Coastguard Worker // Filter video_codecs (which includes all codecs, with correctly remapped
2402*d9f75844SAndroid Build Coastguard Worker // payload types) based on transceiver direction.
2403*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& supported_video_codecs =
2404*d9f75844SAndroid Build Coastguard Worker GetVideoCodecsForOffer(media_description_options.direction);
2405*d9f75844SAndroid Build Coastguard Worker
2406*d9f75844SAndroid Build Coastguard Worker VideoCodecs filtered_codecs;
2407*d9f75844SAndroid Build Coastguard Worker
2408*d9f75844SAndroid Build Coastguard Worker if (!media_description_options.codec_preferences.empty()) {
2409*d9f75844SAndroid Build Coastguard Worker // Add the codecs from the current transceiver's codec preferences.
2410*d9f75844SAndroid Build Coastguard Worker // They override any existing codecs from previous negotiations.
2411*d9f75844SAndroid Build Coastguard Worker filtered_codecs = MatchCodecPreference(
2412*d9f75844SAndroid Build Coastguard Worker media_description_options.codec_preferences, video_codecs,
2413*d9f75844SAndroid Build Coastguard Worker supported_video_codecs, field_trials);
2414*d9f75844SAndroid Build Coastguard Worker } else {
2415*d9f75844SAndroid Build Coastguard Worker // Add the codecs from current content if it exists and is not rejected nor
2416*d9f75844SAndroid Build Coastguard Worker // recycled.
2417*d9f75844SAndroid Build Coastguard Worker if (current_content && !current_content->rejected &&
2418*d9f75844SAndroid Build Coastguard Worker current_content->name == media_description_options.mid) {
2419*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_VIDEO));
2420*d9f75844SAndroid Build Coastguard Worker const VideoContentDescription* vcd =
2421*d9f75844SAndroid Build Coastguard Worker current_content->media_description()->as_video();
2422*d9f75844SAndroid Build Coastguard Worker for (const VideoCodec& codec : vcd->codecs()) {
2423*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<VideoCodec>(vcd->codecs(), video_codecs, codec,
2424*d9f75844SAndroid Build Coastguard Worker nullptr, field_trials)) {
2425*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(codec);
2426*d9f75844SAndroid Build Coastguard Worker }
2427*d9f75844SAndroid Build Coastguard Worker }
2428*d9f75844SAndroid Build Coastguard Worker }
2429*d9f75844SAndroid Build Coastguard Worker // Add other supported video codecs.
2430*d9f75844SAndroid Build Coastguard Worker VideoCodec found_codec;
2431*d9f75844SAndroid Build Coastguard Worker for (const VideoCodec& codec : supported_video_codecs) {
2432*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<VideoCodec>(supported_video_codecs, video_codecs,
2433*d9f75844SAndroid Build Coastguard Worker codec, &found_codec, field_trials) &&
2434*d9f75844SAndroid Build Coastguard Worker !FindMatchingCodec<VideoCodec>(supported_video_codecs,
2435*d9f75844SAndroid Build Coastguard Worker filtered_codecs, codec, nullptr,
2436*d9f75844SAndroid Build Coastguard Worker field_trials)) {
2437*d9f75844SAndroid Build Coastguard Worker // Use the `found_codec` from `video_codecs` because it has the
2438*d9f75844SAndroid Build Coastguard Worker // correctly mapped payload type.
2439*d9f75844SAndroid Build Coastguard Worker if (IsRtxCodec(codec)) {
2440*d9f75844SAndroid Build Coastguard Worker // For RTX we might need to adjust the apt parameter if we got a
2441*d9f75844SAndroid Build Coastguard Worker // remote offer without RTX for a codec for which we support RTX.
2442*d9f75844SAndroid Build Coastguard Worker auto referenced_codec =
2443*d9f75844SAndroid Build Coastguard Worker GetAssociatedCodecForRtx(supported_video_codecs, codec);
2444*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(referenced_codec);
2445*d9f75844SAndroid Build Coastguard Worker
2446*d9f75844SAndroid Build Coastguard Worker // Find the codec we should be referencing and point to it.
2447*d9f75844SAndroid Build Coastguard Worker VideoCodec changed_referenced_codec;
2448*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<VideoCodec>(
2449*d9f75844SAndroid Build Coastguard Worker supported_video_codecs, filtered_codecs, *referenced_codec,
2450*d9f75844SAndroid Build Coastguard Worker &changed_referenced_codec, field_trials)) {
2451*d9f75844SAndroid Build Coastguard Worker found_codec.SetParam(kCodecParamAssociatedPayloadType,
2452*d9f75844SAndroid Build Coastguard Worker changed_referenced_codec.id);
2453*d9f75844SAndroid Build Coastguard Worker }
2454*d9f75844SAndroid Build Coastguard Worker }
2455*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(found_codec);
2456*d9f75844SAndroid Build Coastguard Worker }
2457*d9f75844SAndroid Build Coastguard Worker }
2458*d9f75844SAndroid Build Coastguard Worker }
2459*d9f75844SAndroid Build Coastguard Worker
2460*d9f75844SAndroid Build Coastguard Worker if (session_options.raw_packetization_for_video) {
2461*d9f75844SAndroid Build Coastguard Worker for (VideoCodec& codec : filtered_codecs) {
2462*d9f75844SAndroid Build Coastguard Worker if (codec.GetCodecType() == VideoCodec::CODEC_VIDEO) {
2463*d9f75844SAndroid Build Coastguard Worker codec.packetization = kPacketizationParamRaw;
2464*d9f75844SAndroid Build Coastguard Worker }
2465*d9f75844SAndroid Build Coastguard Worker }
2466*d9f75844SAndroid Build Coastguard Worker }
2467*d9f75844SAndroid Build Coastguard Worker
2468*d9f75844SAndroid Build Coastguard Worker cricket::SecurePolicy sdes_policy =
2469*d9f75844SAndroid Build Coastguard Worker IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
2470*d9f75844SAndroid Build Coastguard Worker : secure();
2471*d9f75844SAndroid Build Coastguard Worker auto video = std::make_unique<VideoContentDescription>();
2472*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> crypto_suites;
2473*d9f75844SAndroid Build Coastguard Worker GetSupportedVideoSdesCryptoSuiteNames(session_options.crypto_options,
2474*d9f75844SAndroid Build Coastguard Worker &crypto_suites);
2475*d9f75844SAndroid Build Coastguard Worker if (!CreateMediaContentOffer(
2476*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options, filtered_codecs,
2477*d9f75844SAndroid Build Coastguard Worker sdes_policy, GetCryptos(current_content), crypto_suites,
2478*d9f75844SAndroid Build Coastguard Worker video_rtp_extensions, ssrc_generator(), current_streams, video.get(),
2479*d9f75844SAndroid Build Coastguard Worker transport_desc_factory_->trials())) {
2480*d9f75844SAndroid Build Coastguard Worker return false;
2481*d9f75844SAndroid Build Coastguard Worker }
2482*d9f75844SAndroid Build Coastguard Worker
2483*d9f75844SAndroid Build Coastguard Worker video->set_bandwidth(kAutoBandwidth);
2484*d9f75844SAndroid Build Coastguard Worker
2485*d9f75844SAndroid Build Coastguard Worker bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
2486*d9f75844SAndroid Build Coastguard Worker SetMediaProtocol(secure_transport, video.get());
2487*d9f75844SAndroid Build Coastguard Worker
2488*d9f75844SAndroid Build Coastguard Worker video->set_direction(media_description_options.direction);
2489*d9f75844SAndroid Build Coastguard Worker
2490*d9f75844SAndroid Build Coastguard Worker desc->AddContent(media_description_options.mid, MediaProtocolType::kRtp,
2491*d9f75844SAndroid Build Coastguard Worker media_description_options.stopped, std::move(video));
2492*d9f75844SAndroid Build Coastguard Worker if (!AddTransportOffer(media_description_options.mid,
2493*d9f75844SAndroid Build Coastguard Worker media_description_options.transport_options,
2494*d9f75844SAndroid Build Coastguard Worker current_description, desc, ice_credentials)) {
2495*d9f75844SAndroid Build Coastguard Worker return false;
2496*d9f75844SAndroid Build Coastguard Worker }
2497*d9f75844SAndroid Build Coastguard Worker
2498*d9f75844SAndroid Build Coastguard Worker return true;
2499*d9f75844SAndroid Build Coastguard Worker }
2500*d9f75844SAndroid Build Coastguard Worker
AddDataContentForOffer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const ContentInfo * current_content,const SessionDescription * current_description,StreamParamsVec * current_streams,SessionDescription * desc,IceCredentialsIterator * ice_credentials) const2501*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddDataContentForOffer(
2502*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
2503*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
2504*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content,
2505*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description,
2506*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
2507*d9f75844SAndroid Build Coastguard Worker SessionDescription* desc,
2508*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2509*d9f75844SAndroid Build Coastguard Worker auto data = std::make_unique<SctpDataContentDescription>();
2510*d9f75844SAndroid Build Coastguard Worker
2511*d9f75844SAndroid Build Coastguard Worker bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
2512*d9f75844SAndroid Build Coastguard Worker
2513*d9f75844SAndroid Build Coastguard Worker cricket::SecurePolicy sdes_policy =
2514*d9f75844SAndroid Build Coastguard Worker IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
2515*d9f75844SAndroid Build Coastguard Worker : secure();
2516*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> crypto_suites;
2517*d9f75844SAndroid Build Coastguard Worker // SDES doesn't make sense for SCTP, so we disable it, and we only
2518*d9f75844SAndroid Build Coastguard Worker // get SDES crypto suites for RTP-based data channels.
2519*d9f75844SAndroid Build Coastguard Worker sdes_policy = cricket::SEC_DISABLED;
2520*d9f75844SAndroid Build Coastguard Worker // Unlike SetMediaProtocol below, we need to set the protocol
2521*d9f75844SAndroid Build Coastguard Worker // before we call CreateMediaContentOffer. Otherwise,
2522*d9f75844SAndroid Build Coastguard Worker // CreateMediaContentOffer won't know this is SCTP and will
2523*d9f75844SAndroid Build Coastguard Worker // generate SSRCs rather than SIDs.
2524*d9f75844SAndroid Build Coastguard Worker data->set_protocol(secure_transport ? kMediaProtocolUdpDtlsSctp
2525*d9f75844SAndroid Build Coastguard Worker : kMediaProtocolSctp);
2526*d9f75844SAndroid Build Coastguard Worker data->set_use_sctpmap(session_options.use_obsolete_sctp_sdp);
2527*d9f75844SAndroid Build Coastguard Worker data->set_max_message_size(kSctpSendBufferSize);
2528*d9f75844SAndroid Build Coastguard Worker
2529*d9f75844SAndroid Build Coastguard Worker if (!CreateContentOffer(media_description_options, session_options,
2530*d9f75844SAndroid Build Coastguard Worker sdes_policy, GetCryptos(current_content),
2531*d9f75844SAndroid Build Coastguard Worker crypto_suites, RtpHeaderExtensions(),
2532*d9f75844SAndroid Build Coastguard Worker ssrc_generator(), current_streams, data.get())) {
2533*d9f75844SAndroid Build Coastguard Worker return false;
2534*d9f75844SAndroid Build Coastguard Worker }
2535*d9f75844SAndroid Build Coastguard Worker
2536*d9f75844SAndroid Build Coastguard Worker desc->AddContent(media_description_options.mid, MediaProtocolType::kSctp,
2537*d9f75844SAndroid Build Coastguard Worker media_description_options.stopped, std::move(data));
2538*d9f75844SAndroid Build Coastguard Worker if (!AddTransportOffer(media_description_options.mid,
2539*d9f75844SAndroid Build Coastguard Worker media_description_options.transport_options,
2540*d9f75844SAndroid Build Coastguard Worker current_description, desc, ice_credentials)) {
2541*d9f75844SAndroid Build Coastguard Worker return false;
2542*d9f75844SAndroid Build Coastguard Worker }
2543*d9f75844SAndroid Build Coastguard Worker return true;
2544*d9f75844SAndroid Build Coastguard Worker }
2545*d9f75844SAndroid Build Coastguard Worker
AddUnsupportedContentForOffer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const ContentInfo * current_content,const SessionDescription * current_description,SessionDescription * desc,IceCredentialsIterator * ice_credentials) const2546*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddUnsupportedContentForOffer(
2547*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
2548*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
2549*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content,
2550*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description,
2551*d9f75844SAndroid Build Coastguard Worker SessionDescription* desc,
2552*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2553*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_UNSUPPORTED));
2554*d9f75844SAndroid Build Coastguard Worker
2555*d9f75844SAndroid Build Coastguard Worker const UnsupportedContentDescription* current_unsupported_description =
2556*d9f75844SAndroid Build Coastguard Worker current_content->media_description()->as_unsupported();
2557*d9f75844SAndroid Build Coastguard Worker auto unsupported = std::make_unique<UnsupportedContentDescription>(
2558*d9f75844SAndroid Build Coastguard Worker current_unsupported_description->media_type());
2559*d9f75844SAndroid Build Coastguard Worker unsupported->set_protocol(current_content->media_description()->protocol());
2560*d9f75844SAndroid Build Coastguard Worker desc->AddContent(media_description_options.mid, MediaProtocolType::kOther,
2561*d9f75844SAndroid Build Coastguard Worker /*rejected=*/true, std::move(unsupported));
2562*d9f75844SAndroid Build Coastguard Worker
2563*d9f75844SAndroid Build Coastguard Worker if (!AddTransportOffer(media_description_options.mid,
2564*d9f75844SAndroid Build Coastguard Worker media_description_options.transport_options,
2565*d9f75844SAndroid Build Coastguard Worker current_description, desc, ice_credentials)) {
2566*d9f75844SAndroid Build Coastguard Worker return false;
2567*d9f75844SAndroid Build Coastguard Worker }
2568*d9f75844SAndroid Build Coastguard Worker return true;
2569*d9f75844SAndroid Build Coastguard Worker }
2570*d9f75844SAndroid Build Coastguard Worker
2571*d9f75844SAndroid Build Coastguard Worker // `audio_codecs` = set of all possible codecs that can be used, with correct
2572*d9f75844SAndroid Build Coastguard Worker // payload type mappings
2573*d9f75844SAndroid Build Coastguard Worker //
2574*d9f75844SAndroid Build Coastguard Worker // `supported_audio_codecs` = set of codecs that are supported for the direction
2575*d9f75844SAndroid Build Coastguard Worker // of this m= section
2576*d9f75844SAndroid Build Coastguard Worker //
2577*d9f75844SAndroid Build Coastguard Worker // acd->codecs() = set of previously negotiated codecs for this m= section
2578*d9f75844SAndroid Build Coastguard Worker //
2579*d9f75844SAndroid Build Coastguard Worker // The payload types should come from audio_codecs, but the order should come
2580*d9f75844SAndroid Build Coastguard Worker // from acd->codecs() and then supported_codecs, to ensure that re-offers don't
2581*d9f75844SAndroid Build Coastguard Worker // change existing codec priority, and that new codecs are added with the right
2582*d9f75844SAndroid Build Coastguard Worker // priority.
AddAudioContentForAnswer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const ContentInfo * offer_content,const SessionDescription * offer_description,const ContentInfo * current_content,const SessionDescription * current_description,const TransportInfo * bundle_transport,const AudioCodecs & audio_codecs,const RtpHeaderExtensions & default_audio_rtp_header_extensions,StreamParamsVec * current_streams,SessionDescription * answer,IceCredentialsIterator * ice_credentials) const2583*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
2584*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
2585*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
2586*d9f75844SAndroid Build Coastguard Worker const ContentInfo* offer_content,
2587*d9f75844SAndroid Build Coastguard Worker const SessionDescription* offer_description,
2588*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content,
2589*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description,
2590*d9f75844SAndroid Build Coastguard Worker const TransportInfo* bundle_transport,
2591*d9f75844SAndroid Build Coastguard Worker const AudioCodecs& audio_codecs,
2592*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& default_audio_rtp_header_extensions,
2593*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
2594*d9f75844SAndroid Build Coastguard Worker SessionDescription* answer,
2595*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2596*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials =
2597*d9f75844SAndroid Build Coastguard Worker &transport_desc_factory_->trials();
2598*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_AUDIO));
2599*d9f75844SAndroid Build Coastguard Worker const AudioContentDescription* offer_audio_description =
2600*d9f75844SAndroid Build Coastguard Worker offer_content->media_description()->as_audio();
2601*d9f75844SAndroid Build Coastguard Worker
2602*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TransportDescription> audio_transport = CreateTransportAnswer(
2603*d9f75844SAndroid Build Coastguard Worker media_description_options.mid, offer_description,
2604*d9f75844SAndroid Build Coastguard Worker media_description_options.transport_options, current_description,
2605*d9f75844SAndroid Build Coastguard Worker bundle_transport != nullptr, ice_credentials);
2606*d9f75844SAndroid Build Coastguard Worker if (!audio_transport) {
2607*d9f75844SAndroid Build Coastguard Worker return false;
2608*d9f75844SAndroid Build Coastguard Worker }
2609*d9f75844SAndroid Build Coastguard Worker
2610*d9f75844SAndroid Build Coastguard Worker // Pick codecs based on the requested communications direction in the offer
2611*d9f75844SAndroid Build Coastguard Worker // and the selected direction in the answer.
2612*d9f75844SAndroid Build Coastguard Worker // Note these will be filtered one final time in CreateMediaContentAnswer.
2613*d9f75844SAndroid Build Coastguard Worker auto wants_rtd = media_description_options.direction;
2614*d9f75844SAndroid Build Coastguard Worker auto offer_rtd = offer_audio_description->direction();
2615*d9f75844SAndroid Build Coastguard Worker auto answer_rtd = NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd);
2616*d9f75844SAndroid Build Coastguard Worker AudioCodecs supported_audio_codecs =
2617*d9f75844SAndroid Build Coastguard Worker GetAudioCodecsForAnswer(offer_rtd, answer_rtd);
2618*d9f75844SAndroid Build Coastguard Worker
2619*d9f75844SAndroid Build Coastguard Worker AudioCodecs filtered_codecs;
2620*d9f75844SAndroid Build Coastguard Worker
2621*d9f75844SAndroid Build Coastguard Worker if (!media_description_options.codec_preferences.empty()) {
2622*d9f75844SAndroid Build Coastguard Worker filtered_codecs = MatchCodecPreference(
2623*d9f75844SAndroid Build Coastguard Worker media_description_options.codec_preferences, audio_codecs,
2624*d9f75844SAndroid Build Coastguard Worker supported_audio_codecs, field_trials);
2625*d9f75844SAndroid Build Coastguard Worker } else {
2626*d9f75844SAndroid Build Coastguard Worker // Add the codecs from current content if it exists and is not rejected nor
2627*d9f75844SAndroid Build Coastguard Worker // recycled.
2628*d9f75844SAndroid Build Coastguard Worker if (current_content && !current_content->rejected &&
2629*d9f75844SAndroid Build Coastguard Worker current_content->name == media_description_options.mid) {
2630*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_AUDIO));
2631*d9f75844SAndroid Build Coastguard Worker const AudioContentDescription* acd =
2632*d9f75844SAndroid Build Coastguard Worker current_content->media_description()->as_audio();
2633*d9f75844SAndroid Build Coastguard Worker for (const AudioCodec& codec : acd->codecs()) {
2634*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<AudioCodec>(acd->codecs(), audio_codecs, codec,
2635*d9f75844SAndroid Build Coastguard Worker nullptr, field_trials)) {
2636*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(codec);
2637*d9f75844SAndroid Build Coastguard Worker }
2638*d9f75844SAndroid Build Coastguard Worker }
2639*d9f75844SAndroid Build Coastguard Worker }
2640*d9f75844SAndroid Build Coastguard Worker // Add other supported audio codecs.
2641*d9f75844SAndroid Build Coastguard Worker for (const AudioCodec& codec : supported_audio_codecs) {
2642*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
2643*d9f75844SAndroid Build Coastguard Worker codec, nullptr, field_trials) &&
2644*d9f75844SAndroid Build Coastguard Worker !FindMatchingCodec<AudioCodec>(supported_audio_codecs,
2645*d9f75844SAndroid Build Coastguard Worker filtered_codecs, codec, nullptr,
2646*d9f75844SAndroid Build Coastguard Worker field_trials)) {
2647*d9f75844SAndroid Build Coastguard Worker // We should use the local codec with local parameters and the codec id
2648*d9f75844SAndroid Build Coastguard Worker // would be correctly mapped in `NegotiateCodecs`.
2649*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(codec);
2650*d9f75844SAndroid Build Coastguard Worker }
2651*d9f75844SAndroid Build Coastguard Worker }
2652*d9f75844SAndroid Build Coastguard Worker }
2653*d9f75844SAndroid Build Coastguard Worker if (!session_options.vad_enabled) {
2654*d9f75844SAndroid Build Coastguard Worker // If application doesn't want CN codecs in answer.
2655*d9f75844SAndroid Build Coastguard Worker StripCNCodecs(&filtered_codecs);
2656*d9f75844SAndroid Build Coastguard Worker }
2657*d9f75844SAndroid Build Coastguard Worker
2658*d9f75844SAndroid Build Coastguard Worker // Determine if we have media codecs in common.
2659*d9f75844SAndroid Build Coastguard Worker bool has_common_media_codecs =
2660*d9f75844SAndroid Build Coastguard Worker std::find_if(filtered_codecs.begin(), filtered_codecs.end(),
2661*d9f75844SAndroid Build Coastguard Worker [](const AudioCodec& c) {
2662*d9f75844SAndroid Build Coastguard Worker return !(IsRedCodec(c) || IsComfortNoiseCodec(c));
2663*d9f75844SAndroid Build Coastguard Worker }) != filtered_codecs.end();
2664*d9f75844SAndroid Build Coastguard Worker
2665*d9f75844SAndroid Build Coastguard Worker bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
2666*d9f75844SAndroid Build Coastguard Worker session_options.bundle_enabled;
2667*d9f75844SAndroid Build Coastguard Worker auto audio_answer = std::make_unique<AudioContentDescription>();
2668*d9f75844SAndroid Build Coastguard Worker // Do not require or create SDES cryptos if DTLS is used.
2669*d9f75844SAndroid Build Coastguard Worker cricket::SecurePolicy sdes_policy =
2670*d9f75844SAndroid Build Coastguard Worker audio_transport->secure() ? cricket::SEC_DISABLED : secure();
2671*d9f75844SAndroid Build Coastguard Worker if (!SetCodecsInAnswer(offer_audio_description, filtered_codecs,
2672*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options,
2673*d9f75844SAndroid Build Coastguard Worker ssrc_generator(), current_streams, audio_answer.get(),
2674*d9f75844SAndroid Build Coastguard Worker transport_desc_factory_->trials())) {
2675*d9f75844SAndroid Build Coastguard Worker return false;
2676*d9f75844SAndroid Build Coastguard Worker }
2677*d9f75844SAndroid Build Coastguard Worker if (!CreateMediaContentAnswer(
2678*d9f75844SAndroid Build Coastguard Worker offer_audio_description, media_description_options, session_options,
2679*d9f75844SAndroid Build Coastguard Worker sdes_policy, GetCryptos(current_content),
2680*d9f75844SAndroid Build Coastguard Worker filtered_rtp_header_extensions(default_audio_rtp_header_extensions),
2681*d9f75844SAndroid Build Coastguard Worker ssrc_generator(), enable_encrypted_rtp_header_extensions_,
2682*d9f75844SAndroid Build Coastguard Worker current_streams, bundle_enabled, audio_answer.get())) {
2683*d9f75844SAndroid Build Coastguard Worker return false; // Fails the session setup.
2684*d9f75844SAndroid Build Coastguard Worker }
2685*d9f75844SAndroid Build Coastguard Worker
2686*d9f75844SAndroid Build Coastguard Worker bool secure = bundle_transport ? bundle_transport->description.secure()
2687*d9f75844SAndroid Build Coastguard Worker : audio_transport->secure();
2688*d9f75844SAndroid Build Coastguard Worker bool rejected = media_description_options.stopped ||
2689*d9f75844SAndroid Build Coastguard Worker offer_content->rejected || !has_common_media_codecs ||
2690*d9f75844SAndroid Build Coastguard Worker !IsMediaProtocolSupported(MEDIA_TYPE_AUDIO,
2691*d9f75844SAndroid Build Coastguard Worker audio_answer->protocol(), secure);
2692*d9f75844SAndroid Build Coastguard Worker if (!AddTransportAnswer(media_description_options.mid,
2693*d9f75844SAndroid Build Coastguard Worker *(audio_transport.get()), answer)) {
2694*d9f75844SAndroid Build Coastguard Worker return false;
2695*d9f75844SAndroid Build Coastguard Worker }
2696*d9f75844SAndroid Build Coastguard Worker
2697*d9f75844SAndroid Build Coastguard Worker if (rejected) {
2698*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Audio m= section '" << media_description_options.mid
2699*d9f75844SAndroid Build Coastguard Worker << "' being rejected in answer.";
2700*d9f75844SAndroid Build Coastguard Worker }
2701*d9f75844SAndroid Build Coastguard Worker
2702*d9f75844SAndroid Build Coastguard Worker answer->AddContent(media_description_options.mid, offer_content->type,
2703*d9f75844SAndroid Build Coastguard Worker rejected, std::move(audio_answer));
2704*d9f75844SAndroid Build Coastguard Worker return true;
2705*d9f75844SAndroid Build Coastguard Worker }
2706*d9f75844SAndroid Build Coastguard Worker
2707*d9f75844SAndroid Build Coastguard Worker // TODO(kron): This function is very similar to AddAudioContentForAnswer.
2708*d9f75844SAndroid Build Coastguard Worker // Refactor to reuse shared code.
AddVideoContentForAnswer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const ContentInfo * offer_content,const SessionDescription * offer_description,const ContentInfo * current_content,const SessionDescription * current_description,const TransportInfo * bundle_transport,const VideoCodecs & video_codecs,const RtpHeaderExtensions & default_video_rtp_header_extensions,StreamParamsVec * current_streams,SessionDescription * answer,IceCredentialsIterator * ice_credentials) const2709*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
2710*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
2711*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
2712*d9f75844SAndroid Build Coastguard Worker const ContentInfo* offer_content,
2713*d9f75844SAndroid Build Coastguard Worker const SessionDescription* offer_description,
2714*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content,
2715*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description,
2716*d9f75844SAndroid Build Coastguard Worker const TransportInfo* bundle_transport,
2717*d9f75844SAndroid Build Coastguard Worker const VideoCodecs& video_codecs,
2718*d9f75844SAndroid Build Coastguard Worker const RtpHeaderExtensions& default_video_rtp_header_extensions,
2719*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
2720*d9f75844SAndroid Build Coastguard Worker SessionDescription* answer,
2721*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2722*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials =
2723*d9f75844SAndroid Build Coastguard Worker &transport_desc_factory_->trials();
2724*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_VIDEO));
2725*d9f75844SAndroid Build Coastguard Worker const VideoContentDescription* offer_video_description =
2726*d9f75844SAndroid Build Coastguard Worker offer_content->media_description()->as_video();
2727*d9f75844SAndroid Build Coastguard Worker
2728*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TransportDescription> video_transport = CreateTransportAnswer(
2729*d9f75844SAndroid Build Coastguard Worker media_description_options.mid, offer_description,
2730*d9f75844SAndroid Build Coastguard Worker media_description_options.transport_options, current_description,
2731*d9f75844SAndroid Build Coastguard Worker bundle_transport != nullptr, ice_credentials);
2732*d9f75844SAndroid Build Coastguard Worker if (!video_transport) {
2733*d9f75844SAndroid Build Coastguard Worker return false;
2734*d9f75844SAndroid Build Coastguard Worker }
2735*d9f75844SAndroid Build Coastguard Worker
2736*d9f75844SAndroid Build Coastguard Worker // Pick codecs based on the requested communications direction in the offer
2737*d9f75844SAndroid Build Coastguard Worker // and the selected direction in the answer.
2738*d9f75844SAndroid Build Coastguard Worker // Note these will be filtered one final time in CreateMediaContentAnswer.
2739*d9f75844SAndroid Build Coastguard Worker auto wants_rtd = media_description_options.direction;
2740*d9f75844SAndroid Build Coastguard Worker auto offer_rtd = offer_video_description->direction();
2741*d9f75844SAndroid Build Coastguard Worker auto answer_rtd = NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd);
2742*d9f75844SAndroid Build Coastguard Worker VideoCodecs supported_video_codecs =
2743*d9f75844SAndroid Build Coastguard Worker GetVideoCodecsForAnswer(offer_rtd, answer_rtd);
2744*d9f75844SAndroid Build Coastguard Worker
2745*d9f75844SAndroid Build Coastguard Worker VideoCodecs filtered_codecs;
2746*d9f75844SAndroid Build Coastguard Worker
2747*d9f75844SAndroid Build Coastguard Worker if (!media_description_options.codec_preferences.empty()) {
2748*d9f75844SAndroid Build Coastguard Worker filtered_codecs = MatchCodecPreference(
2749*d9f75844SAndroid Build Coastguard Worker media_description_options.codec_preferences, video_codecs,
2750*d9f75844SAndroid Build Coastguard Worker supported_video_codecs, field_trials);
2751*d9f75844SAndroid Build Coastguard Worker } else {
2752*d9f75844SAndroid Build Coastguard Worker // Add the codecs from current content if it exists and is not rejected nor
2753*d9f75844SAndroid Build Coastguard Worker // recycled.
2754*d9f75844SAndroid Build Coastguard Worker if (current_content && !current_content->rejected &&
2755*d9f75844SAndroid Build Coastguard Worker current_content->name == media_description_options.mid) {
2756*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_VIDEO));
2757*d9f75844SAndroid Build Coastguard Worker const VideoContentDescription* vcd =
2758*d9f75844SAndroid Build Coastguard Worker current_content->media_description()->as_video();
2759*d9f75844SAndroid Build Coastguard Worker for (const VideoCodec& codec : vcd->codecs()) {
2760*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<VideoCodec>(vcd->codecs(), video_codecs, codec,
2761*d9f75844SAndroid Build Coastguard Worker nullptr, field_trials)) {
2762*d9f75844SAndroid Build Coastguard Worker filtered_codecs.push_back(codec);
2763*d9f75844SAndroid Build Coastguard Worker }
2764*d9f75844SAndroid Build Coastguard Worker }
2765*d9f75844SAndroid Build Coastguard Worker }
2766*d9f75844SAndroid Build Coastguard Worker
2767*d9f75844SAndroid Build Coastguard Worker // Add other supported video codecs.
2768*d9f75844SAndroid Build Coastguard Worker VideoCodecs other_video_codecs;
2769*d9f75844SAndroid Build Coastguard Worker for (const VideoCodec& codec : supported_video_codecs) {
2770*d9f75844SAndroid Build Coastguard Worker if (FindMatchingCodec<VideoCodec>(supported_video_codecs, video_codecs,
2771*d9f75844SAndroid Build Coastguard Worker codec, nullptr, field_trials) &&
2772*d9f75844SAndroid Build Coastguard Worker !FindMatchingCodec<VideoCodec>(supported_video_codecs,
2773*d9f75844SAndroid Build Coastguard Worker filtered_codecs, codec, nullptr,
2774*d9f75844SAndroid Build Coastguard Worker field_trials)) {
2775*d9f75844SAndroid Build Coastguard Worker // We should use the local codec with local parameters and the codec id
2776*d9f75844SAndroid Build Coastguard Worker // would be correctly mapped in `NegotiateCodecs`.
2777*d9f75844SAndroid Build Coastguard Worker other_video_codecs.push_back(codec);
2778*d9f75844SAndroid Build Coastguard Worker }
2779*d9f75844SAndroid Build Coastguard Worker }
2780*d9f75844SAndroid Build Coastguard Worker
2781*d9f75844SAndroid Build Coastguard Worker // Use ComputeCodecsUnion to avoid having duplicate payload IDs
2782*d9f75844SAndroid Build Coastguard Worker filtered_codecs = ComputeCodecsUnion<VideoCodec>(
2783*d9f75844SAndroid Build Coastguard Worker filtered_codecs, other_video_codecs, field_trials);
2784*d9f75844SAndroid Build Coastguard Worker }
2785*d9f75844SAndroid Build Coastguard Worker // Determine if we have media codecs in common.
2786*d9f75844SAndroid Build Coastguard Worker bool has_common_media_codecs =
2787*d9f75844SAndroid Build Coastguard Worker std::find_if(
2788*d9f75844SAndroid Build Coastguard Worker filtered_codecs.begin(), filtered_codecs.end(),
2789*d9f75844SAndroid Build Coastguard Worker [](const VideoCodec& c) {
2790*d9f75844SAndroid Build Coastguard Worker return !(IsRedCodec(c) || IsUlpfecCodec(c) || IsFlexfecCodec(c));
2791*d9f75844SAndroid Build Coastguard Worker }) != filtered_codecs.end();
2792*d9f75844SAndroid Build Coastguard Worker
2793*d9f75844SAndroid Build Coastguard Worker if (session_options.raw_packetization_for_video) {
2794*d9f75844SAndroid Build Coastguard Worker for (VideoCodec& codec : filtered_codecs) {
2795*d9f75844SAndroid Build Coastguard Worker if (codec.GetCodecType() == VideoCodec::CODEC_VIDEO) {
2796*d9f75844SAndroid Build Coastguard Worker codec.packetization = kPacketizationParamRaw;
2797*d9f75844SAndroid Build Coastguard Worker }
2798*d9f75844SAndroid Build Coastguard Worker }
2799*d9f75844SAndroid Build Coastguard Worker }
2800*d9f75844SAndroid Build Coastguard Worker
2801*d9f75844SAndroid Build Coastguard Worker bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
2802*d9f75844SAndroid Build Coastguard Worker session_options.bundle_enabled;
2803*d9f75844SAndroid Build Coastguard Worker auto video_answer = std::make_unique<VideoContentDescription>();
2804*d9f75844SAndroid Build Coastguard Worker // Do not require or create SDES cryptos if DTLS is used.
2805*d9f75844SAndroid Build Coastguard Worker cricket::SecurePolicy sdes_policy =
2806*d9f75844SAndroid Build Coastguard Worker video_transport->secure() ? cricket::SEC_DISABLED : secure();
2807*d9f75844SAndroid Build Coastguard Worker if (!SetCodecsInAnswer(offer_video_description, filtered_codecs,
2808*d9f75844SAndroid Build Coastguard Worker media_description_options, session_options,
2809*d9f75844SAndroid Build Coastguard Worker ssrc_generator(), current_streams, video_answer.get(),
2810*d9f75844SAndroid Build Coastguard Worker transport_desc_factory_->trials())) {
2811*d9f75844SAndroid Build Coastguard Worker return false;
2812*d9f75844SAndroid Build Coastguard Worker }
2813*d9f75844SAndroid Build Coastguard Worker if (!CreateMediaContentAnswer(
2814*d9f75844SAndroid Build Coastguard Worker offer_video_description, media_description_options, session_options,
2815*d9f75844SAndroid Build Coastguard Worker sdes_policy, GetCryptos(current_content),
2816*d9f75844SAndroid Build Coastguard Worker filtered_rtp_header_extensions(default_video_rtp_header_extensions),
2817*d9f75844SAndroid Build Coastguard Worker ssrc_generator(), enable_encrypted_rtp_header_extensions_,
2818*d9f75844SAndroid Build Coastguard Worker current_streams, bundle_enabled, video_answer.get())) {
2819*d9f75844SAndroid Build Coastguard Worker return false; // Failed the session setup.
2820*d9f75844SAndroid Build Coastguard Worker }
2821*d9f75844SAndroid Build Coastguard Worker bool secure = bundle_transport ? bundle_transport->description.secure()
2822*d9f75844SAndroid Build Coastguard Worker : video_transport->secure();
2823*d9f75844SAndroid Build Coastguard Worker bool rejected = media_description_options.stopped ||
2824*d9f75844SAndroid Build Coastguard Worker offer_content->rejected || !has_common_media_codecs ||
2825*d9f75844SAndroid Build Coastguard Worker !IsMediaProtocolSupported(MEDIA_TYPE_VIDEO,
2826*d9f75844SAndroid Build Coastguard Worker video_answer->protocol(), secure);
2827*d9f75844SAndroid Build Coastguard Worker if (!AddTransportAnswer(media_description_options.mid,
2828*d9f75844SAndroid Build Coastguard Worker *(video_transport.get()), answer)) {
2829*d9f75844SAndroid Build Coastguard Worker return false;
2830*d9f75844SAndroid Build Coastguard Worker }
2831*d9f75844SAndroid Build Coastguard Worker
2832*d9f75844SAndroid Build Coastguard Worker if (!rejected) {
2833*d9f75844SAndroid Build Coastguard Worker video_answer->set_bandwidth(kAutoBandwidth);
2834*d9f75844SAndroid Build Coastguard Worker } else {
2835*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Video m= section '" << media_description_options.mid
2836*d9f75844SAndroid Build Coastguard Worker << "' being rejected in answer.";
2837*d9f75844SAndroid Build Coastguard Worker }
2838*d9f75844SAndroid Build Coastguard Worker answer->AddContent(media_description_options.mid, offer_content->type,
2839*d9f75844SAndroid Build Coastguard Worker rejected, std::move(video_answer));
2840*d9f75844SAndroid Build Coastguard Worker return true;
2841*d9f75844SAndroid Build Coastguard Worker }
2842*d9f75844SAndroid Build Coastguard Worker
AddDataContentForAnswer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const ContentInfo * offer_content,const SessionDescription * offer_description,const ContentInfo * current_content,const SessionDescription * current_description,const TransportInfo * bundle_transport,StreamParamsVec * current_streams,SessionDescription * answer,IceCredentialsIterator * ice_credentials) const2843*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
2844*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
2845*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
2846*d9f75844SAndroid Build Coastguard Worker const ContentInfo* offer_content,
2847*d9f75844SAndroid Build Coastguard Worker const SessionDescription* offer_description,
2848*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content,
2849*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description,
2850*d9f75844SAndroid Build Coastguard Worker const TransportInfo* bundle_transport,
2851*d9f75844SAndroid Build Coastguard Worker StreamParamsVec* current_streams,
2852*d9f75844SAndroid Build Coastguard Worker SessionDescription* answer,
2853*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2854*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TransportDescription> data_transport = CreateTransportAnswer(
2855*d9f75844SAndroid Build Coastguard Worker media_description_options.mid, offer_description,
2856*d9f75844SAndroid Build Coastguard Worker media_description_options.transport_options, current_description,
2857*d9f75844SAndroid Build Coastguard Worker bundle_transport != nullptr, ice_credentials);
2858*d9f75844SAndroid Build Coastguard Worker if (!data_transport) {
2859*d9f75844SAndroid Build Coastguard Worker return false;
2860*d9f75844SAndroid Build Coastguard Worker }
2861*d9f75844SAndroid Build Coastguard Worker
2862*d9f75844SAndroid Build Coastguard Worker // Do not require or create SDES cryptos if DTLS is used.
2863*d9f75844SAndroid Build Coastguard Worker cricket::SecurePolicy sdes_policy =
2864*d9f75844SAndroid Build Coastguard Worker data_transport->secure() ? cricket::SEC_DISABLED : secure();
2865*d9f75844SAndroid Build Coastguard Worker bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
2866*d9f75844SAndroid Build Coastguard Worker session_options.bundle_enabled;
2867*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_DATA));
2868*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<MediaContentDescription> data_answer;
2869*d9f75844SAndroid Build Coastguard Worker if (offer_content->media_description()->as_sctp()) {
2870*d9f75844SAndroid Build Coastguard Worker // SCTP data content
2871*d9f75844SAndroid Build Coastguard Worker data_answer = std::make_unique<SctpDataContentDescription>();
2872*d9f75844SAndroid Build Coastguard Worker const SctpDataContentDescription* offer_data_description =
2873*d9f75844SAndroid Build Coastguard Worker offer_content->media_description()->as_sctp();
2874*d9f75844SAndroid Build Coastguard Worker // Respond with the offerer's proto, whatever it is.
2875*d9f75844SAndroid Build Coastguard Worker data_answer->as_sctp()->set_protocol(offer_data_description->protocol());
2876*d9f75844SAndroid Build Coastguard Worker // Respond with our max message size or the remote max messsage size,
2877*d9f75844SAndroid Build Coastguard Worker // whichever is smaller.
2878*d9f75844SAndroid Build Coastguard Worker // 0 is treated specially - it means "I can accept any size". Since
2879*d9f75844SAndroid Build Coastguard Worker // we do not implement infinite size messages, reply with
2880*d9f75844SAndroid Build Coastguard Worker // kSctpSendBufferSize.
2881*d9f75844SAndroid Build Coastguard Worker if (offer_data_description->max_message_size() == 0) {
2882*d9f75844SAndroid Build Coastguard Worker data_answer->as_sctp()->set_max_message_size(kSctpSendBufferSize);
2883*d9f75844SAndroid Build Coastguard Worker } else {
2884*d9f75844SAndroid Build Coastguard Worker data_answer->as_sctp()->set_max_message_size(std::min(
2885*d9f75844SAndroid Build Coastguard Worker offer_data_description->max_message_size(), kSctpSendBufferSize));
2886*d9f75844SAndroid Build Coastguard Worker }
2887*d9f75844SAndroid Build Coastguard Worker if (!CreateMediaContentAnswer(
2888*d9f75844SAndroid Build Coastguard Worker offer_data_description, media_description_options, session_options,
2889*d9f75844SAndroid Build Coastguard Worker sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(),
2890*d9f75844SAndroid Build Coastguard Worker ssrc_generator(), enable_encrypted_rtp_header_extensions_,
2891*d9f75844SAndroid Build Coastguard Worker current_streams, bundle_enabled, data_answer.get())) {
2892*d9f75844SAndroid Build Coastguard Worker return false; // Fails the session setup.
2893*d9f75844SAndroid Build Coastguard Worker }
2894*d9f75844SAndroid Build Coastguard Worker // Respond with sctpmap if the offer uses sctpmap.
2895*d9f75844SAndroid Build Coastguard Worker bool offer_uses_sctpmap = offer_data_description->use_sctpmap();
2896*d9f75844SAndroid Build Coastguard Worker data_answer->as_sctp()->set_use_sctpmap(offer_uses_sctpmap);
2897*d9f75844SAndroid Build Coastguard Worker } else {
2898*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK_NOTREACHED() << "Non-SCTP data content found";
2899*d9f75844SAndroid Build Coastguard Worker }
2900*d9f75844SAndroid Build Coastguard Worker
2901*d9f75844SAndroid Build Coastguard Worker bool secure = bundle_transport ? bundle_transport->description.secure()
2902*d9f75844SAndroid Build Coastguard Worker : data_transport->secure();
2903*d9f75844SAndroid Build Coastguard Worker
2904*d9f75844SAndroid Build Coastguard Worker bool rejected = media_description_options.stopped ||
2905*d9f75844SAndroid Build Coastguard Worker offer_content->rejected ||
2906*d9f75844SAndroid Build Coastguard Worker !IsMediaProtocolSupported(MEDIA_TYPE_DATA,
2907*d9f75844SAndroid Build Coastguard Worker data_answer->protocol(), secure);
2908*d9f75844SAndroid Build Coastguard Worker if (!AddTransportAnswer(media_description_options.mid,
2909*d9f75844SAndroid Build Coastguard Worker *(data_transport.get()), answer)) {
2910*d9f75844SAndroid Build Coastguard Worker return false;
2911*d9f75844SAndroid Build Coastguard Worker }
2912*d9f75844SAndroid Build Coastguard Worker
2913*d9f75844SAndroid Build Coastguard Worker answer->AddContent(media_description_options.mid, offer_content->type,
2914*d9f75844SAndroid Build Coastguard Worker rejected, std::move(data_answer));
2915*d9f75844SAndroid Build Coastguard Worker return true;
2916*d9f75844SAndroid Build Coastguard Worker }
2917*d9f75844SAndroid Build Coastguard Worker
AddUnsupportedContentForAnswer(const MediaDescriptionOptions & media_description_options,const MediaSessionOptions & session_options,const ContentInfo * offer_content,const SessionDescription * offer_description,const ContentInfo * current_content,const SessionDescription * current_description,const TransportInfo * bundle_transport,SessionDescription * answer,IceCredentialsIterator * ice_credentials) const2918*d9f75844SAndroid Build Coastguard Worker bool MediaSessionDescriptionFactory::AddUnsupportedContentForAnswer(
2919*d9f75844SAndroid Build Coastguard Worker const MediaDescriptionOptions& media_description_options,
2920*d9f75844SAndroid Build Coastguard Worker const MediaSessionOptions& session_options,
2921*d9f75844SAndroid Build Coastguard Worker const ContentInfo* offer_content,
2922*d9f75844SAndroid Build Coastguard Worker const SessionDescription* offer_description,
2923*d9f75844SAndroid Build Coastguard Worker const ContentInfo* current_content,
2924*d9f75844SAndroid Build Coastguard Worker const SessionDescription* current_description,
2925*d9f75844SAndroid Build Coastguard Worker const TransportInfo* bundle_transport,
2926*d9f75844SAndroid Build Coastguard Worker SessionDescription* answer,
2927*d9f75844SAndroid Build Coastguard Worker IceCredentialsIterator* ice_credentials) const {
2928*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<TransportDescription> unsupported_transport =
2929*d9f75844SAndroid Build Coastguard Worker CreateTransportAnswer(media_description_options.mid, offer_description,
2930*d9f75844SAndroid Build Coastguard Worker media_description_options.transport_options,
2931*d9f75844SAndroid Build Coastguard Worker current_description, bundle_transport != nullptr,
2932*d9f75844SAndroid Build Coastguard Worker ice_credentials);
2933*d9f75844SAndroid Build Coastguard Worker if (!unsupported_transport) {
2934*d9f75844SAndroid Build Coastguard Worker return false;
2935*d9f75844SAndroid Build Coastguard Worker }
2936*d9f75844SAndroid Build Coastguard Worker RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_UNSUPPORTED));
2937*d9f75844SAndroid Build Coastguard Worker
2938*d9f75844SAndroid Build Coastguard Worker const UnsupportedContentDescription* offer_unsupported_description =
2939*d9f75844SAndroid Build Coastguard Worker offer_content->media_description()->as_unsupported();
2940*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<MediaContentDescription> unsupported_answer =
2941*d9f75844SAndroid Build Coastguard Worker std::make_unique<UnsupportedContentDescription>(
2942*d9f75844SAndroid Build Coastguard Worker offer_unsupported_description->media_type());
2943*d9f75844SAndroid Build Coastguard Worker unsupported_answer->set_protocol(offer_unsupported_description->protocol());
2944*d9f75844SAndroid Build Coastguard Worker
2945*d9f75844SAndroid Build Coastguard Worker if (!AddTransportAnswer(media_description_options.mid,
2946*d9f75844SAndroid Build Coastguard Worker *(unsupported_transport.get()), answer)) {
2947*d9f75844SAndroid Build Coastguard Worker return false;
2948*d9f75844SAndroid Build Coastguard Worker }
2949*d9f75844SAndroid Build Coastguard Worker answer->AddContent(media_description_options.mid, offer_content->type,
2950*d9f75844SAndroid Build Coastguard Worker /*rejected=*/true, std::move(unsupported_answer));
2951*d9f75844SAndroid Build Coastguard Worker return true;
2952*d9f75844SAndroid Build Coastguard Worker }
2953*d9f75844SAndroid Build Coastguard Worker
ComputeAudioCodecsIntersectionAndUnion()2954*d9f75844SAndroid Build Coastguard Worker void MediaSessionDescriptionFactory::ComputeAudioCodecsIntersectionAndUnion() {
2955*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials =
2956*d9f75844SAndroid Build Coastguard Worker &transport_desc_factory_->trials();
2957*d9f75844SAndroid Build Coastguard Worker audio_sendrecv_codecs_.clear();
2958*d9f75844SAndroid Build Coastguard Worker all_audio_codecs_.clear();
2959*d9f75844SAndroid Build Coastguard Worker // Compute the audio codecs union.
2960*d9f75844SAndroid Build Coastguard Worker for (const AudioCodec& send : audio_send_codecs_) {
2961*d9f75844SAndroid Build Coastguard Worker all_audio_codecs_.push_back(send);
2962*d9f75844SAndroid Build Coastguard Worker if (!FindMatchingCodec<AudioCodec>(audio_send_codecs_, audio_recv_codecs_,
2963*d9f75844SAndroid Build Coastguard Worker send, nullptr, field_trials)) {
2964*d9f75844SAndroid Build Coastguard Worker // It doesn't make sense to have an RTX codec we support sending but not
2965*d9f75844SAndroid Build Coastguard Worker // receiving.
2966*d9f75844SAndroid Build Coastguard Worker RTC_DCHECK(!IsRtxCodec(send));
2967*d9f75844SAndroid Build Coastguard Worker }
2968*d9f75844SAndroid Build Coastguard Worker }
2969*d9f75844SAndroid Build Coastguard Worker for (const AudioCodec& recv : audio_recv_codecs_) {
2970*d9f75844SAndroid Build Coastguard Worker if (!FindMatchingCodec<AudioCodec>(audio_recv_codecs_, audio_send_codecs_,
2971*d9f75844SAndroid Build Coastguard Worker recv, nullptr, field_trials)) {
2972*d9f75844SAndroid Build Coastguard Worker all_audio_codecs_.push_back(recv);
2973*d9f75844SAndroid Build Coastguard Worker }
2974*d9f75844SAndroid Build Coastguard Worker }
2975*d9f75844SAndroid Build Coastguard Worker // Use NegotiateCodecs to merge our codec lists, since the operation is
2976*d9f75844SAndroid Build Coastguard Worker // essentially the same. Put send_codecs as the offered_codecs, which is the
2977*d9f75844SAndroid Build Coastguard Worker // order we'd like to follow. The reasoning is that encoding is usually more
2978*d9f75844SAndroid Build Coastguard Worker // expensive than decoding, and prioritizing a codec in the send list probably
2979*d9f75844SAndroid Build Coastguard Worker // means it's a codec we can handle efficiently.
2980*d9f75844SAndroid Build Coastguard Worker NegotiateCodecs(audio_recv_codecs_, audio_send_codecs_,
2981*d9f75844SAndroid Build Coastguard Worker &audio_sendrecv_codecs_, true, field_trials);
2982*d9f75844SAndroid Build Coastguard Worker }
2983*d9f75844SAndroid Build Coastguard Worker
ComputeVideoCodecsIntersectionAndUnion()2984*d9f75844SAndroid Build Coastguard Worker void MediaSessionDescriptionFactory::ComputeVideoCodecsIntersectionAndUnion() {
2985*d9f75844SAndroid Build Coastguard Worker const webrtc::FieldTrialsView* field_trials =
2986*d9f75844SAndroid Build Coastguard Worker &transport_desc_factory_->trials();
2987*d9f75844SAndroid Build Coastguard Worker video_sendrecv_codecs_.clear();
2988*d9f75844SAndroid Build Coastguard Worker
2989*d9f75844SAndroid Build Coastguard Worker // Use ComputeCodecsUnion to avoid having duplicate payload IDs
2990*d9f75844SAndroid Build Coastguard Worker all_video_codecs_ =
2991*d9f75844SAndroid Build Coastguard Worker ComputeCodecsUnion(video_recv_codecs_, video_send_codecs_, field_trials);
2992*d9f75844SAndroid Build Coastguard Worker
2993*d9f75844SAndroid Build Coastguard Worker // Use NegotiateCodecs to merge our codec lists, since the operation is
2994*d9f75844SAndroid Build Coastguard Worker // essentially the same. Put send_codecs as the offered_codecs, which is the
2995*d9f75844SAndroid Build Coastguard Worker // order we'd like to follow. The reasoning is that encoding is usually more
2996*d9f75844SAndroid Build Coastguard Worker // expensive than decoding, and prioritizing a codec in the send list probably
2997*d9f75844SAndroid Build Coastguard Worker // means it's a codec we can handle efficiently.
2998*d9f75844SAndroid Build Coastguard Worker NegotiateCodecs(video_recv_codecs_, video_send_codecs_,
2999*d9f75844SAndroid Build Coastguard Worker &video_sendrecv_codecs_, true, field_trials);
3000*d9f75844SAndroid Build Coastguard Worker }
3001*d9f75844SAndroid Build Coastguard Worker
IsMediaContent(const ContentInfo * content)3002*d9f75844SAndroid Build Coastguard Worker bool IsMediaContent(const ContentInfo* content) {
3003*d9f75844SAndroid Build Coastguard Worker return (content && (content->type == MediaProtocolType::kRtp ||
3004*d9f75844SAndroid Build Coastguard Worker content->type == MediaProtocolType::kSctp));
3005*d9f75844SAndroid Build Coastguard Worker }
3006*d9f75844SAndroid Build Coastguard Worker
IsAudioContent(const ContentInfo * content)3007*d9f75844SAndroid Build Coastguard Worker bool IsAudioContent(const ContentInfo* content) {
3008*d9f75844SAndroid Build Coastguard Worker return IsMediaContentOfType(content, MEDIA_TYPE_AUDIO);
3009*d9f75844SAndroid Build Coastguard Worker }
3010*d9f75844SAndroid Build Coastguard Worker
IsVideoContent(const ContentInfo * content)3011*d9f75844SAndroid Build Coastguard Worker bool IsVideoContent(const ContentInfo* content) {
3012*d9f75844SAndroid Build Coastguard Worker return IsMediaContentOfType(content, MEDIA_TYPE_VIDEO);
3013*d9f75844SAndroid Build Coastguard Worker }
3014*d9f75844SAndroid Build Coastguard Worker
IsDataContent(const ContentInfo * content)3015*d9f75844SAndroid Build Coastguard Worker bool IsDataContent(const ContentInfo* content) {
3016*d9f75844SAndroid Build Coastguard Worker return IsMediaContentOfType(content, MEDIA_TYPE_DATA);
3017*d9f75844SAndroid Build Coastguard Worker }
3018*d9f75844SAndroid Build Coastguard Worker
IsUnsupportedContent(const ContentInfo * content)3019*d9f75844SAndroid Build Coastguard Worker bool IsUnsupportedContent(const ContentInfo* content) {
3020*d9f75844SAndroid Build Coastguard Worker return IsMediaContentOfType(content, MEDIA_TYPE_UNSUPPORTED);
3021*d9f75844SAndroid Build Coastguard Worker }
3022*d9f75844SAndroid Build Coastguard Worker
GetFirstMediaContent(const ContentInfos & contents,MediaType media_type)3023*d9f75844SAndroid Build Coastguard Worker const ContentInfo* GetFirstMediaContent(const ContentInfos& contents,
3024*d9f75844SAndroid Build Coastguard Worker MediaType media_type) {
3025*d9f75844SAndroid Build Coastguard Worker for (const ContentInfo& content : contents) {
3026*d9f75844SAndroid Build Coastguard Worker if (IsMediaContentOfType(&content, media_type)) {
3027*d9f75844SAndroid Build Coastguard Worker return &content;
3028*d9f75844SAndroid Build Coastguard Worker }
3029*d9f75844SAndroid Build Coastguard Worker }
3030*d9f75844SAndroid Build Coastguard Worker return nullptr;
3031*d9f75844SAndroid Build Coastguard Worker }
3032*d9f75844SAndroid Build Coastguard Worker
GetFirstAudioContent(const ContentInfos & contents)3033*d9f75844SAndroid Build Coastguard Worker const ContentInfo* GetFirstAudioContent(const ContentInfos& contents) {
3034*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(contents, MEDIA_TYPE_AUDIO);
3035*d9f75844SAndroid Build Coastguard Worker }
3036*d9f75844SAndroid Build Coastguard Worker
GetFirstVideoContent(const ContentInfos & contents)3037*d9f75844SAndroid Build Coastguard Worker const ContentInfo* GetFirstVideoContent(const ContentInfos& contents) {
3038*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(contents, MEDIA_TYPE_VIDEO);
3039*d9f75844SAndroid Build Coastguard Worker }
3040*d9f75844SAndroid Build Coastguard Worker
GetFirstDataContent(const ContentInfos & contents)3041*d9f75844SAndroid Build Coastguard Worker const ContentInfo* GetFirstDataContent(const ContentInfos& contents) {
3042*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(contents, MEDIA_TYPE_DATA);
3043*d9f75844SAndroid Build Coastguard Worker }
3044*d9f75844SAndroid Build Coastguard Worker
GetFirstMediaContent(const SessionDescription * sdesc,MediaType media_type)3045*d9f75844SAndroid Build Coastguard Worker const ContentInfo* GetFirstMediaContent(const SessionDescription* sdesc,
3046*d9f75844SAndroid Build Coastguard Worker MediaType media_type) {
3047*d9f75844SAndroid Build Coastguard Worker if (sdesc == nullptr) {
3048*d9f75844SAndroid Build Coastguard Worker return nullptr;
3049*d9f75844SAndroid Build Coastguard Worker }
3050*d9f75844SAndroid Build Coastguard Worker
3051*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(sdesc->contents(), media_type);
3052*d9f75844SAndroid Build Coastguard Worker }
3053*d9f75844SAndroid Build Coastguard Worker
GetFirstAudioContent(const SessionDescription * sdesc)3054*d9f75844SAndroid Build Coastguard Worker const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc) {
3055*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(sdesc, MEDIA_TYPE_AUDIO);
3056*d9f75844SAndroid Build Coastguard Worker }
3057*d9f75844SAndroid Build Coastguard Worker
GetFirstVideoContent(const SessionDescription * sdesc)3058*d9f75844SAndroid Build Coastguard Worker const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc) {
3059*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(sdesc, MEDIA_TYPE_VIDEO);
3060*d9f75844SAndroid Build Coastguard Worker }
3061*d9f75844SAndroid Build Coastguard Worker
GetFirstDataContent(const SessionDescription * sdesc)3062*d9f75844SAndroid Build Coastguard Worker const ContentInfo* GetFirstDataContent(const SessionDescription* sdesc) {
3063*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(sdesc, MEDIA_TYPE_DATA);
3064*d9f75844SAndroid Build Coastguard Worker }
3065*d9f75844SAndroid Build Coastguard Worker
GetFirstMediaContentDescription(const SessionDescription * sdesc,MediaType media_type)3066*d9f75844SAndroid Build Coastguard Worker const MediaContentDescription* GetFirstMediaContentDescription(
3067*d9f75844SAndroid Build Coastguard Worker const SessionDescription* sdesc,
3068*d9f75844SAndroid Build Coastguard Worker MediaType media_type) {
3069*d9f75844SAndroid Build Coastguard Worker const ContentInfo* content = GetFirstMediaContent(sdesc, media_type);
3070*d9f75844SAndroid Build Coastguard Worker return (content ? content->media_description() : nullptr);
3071*d9f75844SAndroid Build Coastguard Worker }
3072*d9f75844SAndroid Build Coastguard Worker
GetFirstAudioContentDescription(const SessionDescription * sdesc)3073*d9f75844SAndroid Build Coastguard Worker const AudioContentDescription* GetFirstAudioContentDescription(
3074*d9f75844SAndroid Build Coastguard Worker const SessionDescription* sdesc) {
3075*d9f75844SAndroid Build Coastguard Worker auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO);
3076*d9f75844SAndroid Build Coastguard Worker return desc ? desc->as_audio() : nullptr;
3077*d9f75844SAndroid Build Coastguard Worker }
3078*d9f75844SAndroid Build Coastguard Worker
GetFirstVideoContentDescription(const SessionDescription * sdesc)3079*d9f75844SAndroid Build Coastguard Worker const VideoContentDescription* GetFirstVideoContentDescription(
3080*d9f75844SAndroid Build Coastguard Worker const SessionDescription* sdesc) {
3081*d9f75844SAndroid Build Coastguard Worker auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO);
3082*d9f75844SAndroid Build Coastguard Worker return desc ? desc->as_video() : nullptr;
3083*d9f75844SAndroid Build Coastguard Worker }
3084*d9f75844SAndroid Build Coastguard Worker
GetFirstSctpDataContentDescription(const SessionDescription * sdesc)3085*d9f75844SAndroid Build Coastguard Worker const SctpDataContentDescription* GetFirstSctpDataContentDescription(
3086*d9f75844SAndroid Build Coastguard Worker const SessionDescription* sdesc) {
3087*d9f75844SAndroid Build Coastguard Worker auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
3088*d9f75844SAndroid Build Coastguard Worker return desc ? desc->as_sctp() : nullptr;
3089*d9f75844SAndroid Build Coastguard Worker }
3090*d9f75844SAndroid Build Coastguard Worker
3091*d9f75844SAndroid Build Coastguard Worker //
3092*d9f75844SAndroid Build Coastguard Worker // Non-const versions of the above functions.
3093*d9f75844SAndroid Build Coastguard Worker //
3094*d9f75844SAndroid Build Coastguard Worker
GetFirstMediaContent(ContentInfos * contents,MediaType media_type)3095*d9f75844SAndroid Build Coastguard Worker ContentInfo* GetFirstMediaContent(ContentInfos* contents,
3096*d9f75844SAndroid Build Coastguard Worker MediaType media_type) {
3097*d9f75844SAndroid Build Coastguard Worker for (ContentInfo& content : *contents) {
3098*d9f75844SAndroid Build Coastguard Worker if (IsMediaContentOfType(&content, media_type)) {
3099*d9f75844SAndroid Build Coastguard Worker return &content;
3100*d9f75844SAndroid Build Coastguard Worker }
3101*d9f75844SAndroid Build Coastguard Worker }
3102*d9f75844SAndroid Build Coastguard Worker return nullptr;
3103*d9f75844SAndroid Build Coastguard Worker }
3104*d9f75844SAndroid Build Coastguard Worker
GetFirstAudioContent(ContentInfos * contents)3105*d9f75844SAndroid Build Coastguard Worker ContentInfo* GetFirstAudioContent(ContentInfos* contents) {
3106*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(contents, MEDIA_TYPE_AUDIO);
3107*d9f75844SAndroid Build Coastguard Worker }
3108*d9f75844SAndroid Build Coastguard Worker
GetFirstVideoContent(ContentInfos * contents)3109*d9f75844SAndroid Build Coastguard Worker ContentInfo* GetFirstVideoContent(ContentInfos* contents) {
3110*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(contents, MEDIA_TYPE_VIDEO);
3111*d9f75844SAndroid Build Coastguard Worker }
3112*d9f75844SAndroid Build Coastguard Worker
GetFirstDataContent(ContentInfos * contents)3113*d9f75844SAndroid Build Coastguard Worker ContentInfo* GetFirstDataContent(ContentInfos* contents) {
3114*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(contents, MEDIA_TYPE_DATA);
3115*d9f75844SAndroid Build Coastguard Worker }
3116*d9f75844SAndroid Build Coastguard Worker
GetFirstMediaContent(SessionDescription * sdesc,MediaType media_type)3117*d9f75844SAndroid Build Coastguard Worker ContentInfo* GetFirstMediaContent(SessionDescription* sdesc,
3118*d9f75844SAndroid Build Coastguard Worker MediaType media_type) {
3119*d9f75844SAndroid Build Coastguard Worker if (sdesc == nullptr) {
3120*d9f75844SAndroid Build Coastguard Worker return nullptr;
3121*d9f75844SAndroid Build Coastguard Worker }
3122*d9f75844SAndroid Build Coastguard Worker
3123*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(&sdesc->contents(), media_type);
3124*d9f75844SAndroid Build Coastguard Worker }
3125*d9f75844SAndroid Build Coastguard Worker
GetFirstAudioContent(SessionDescription * sdesc)3126*d9f75844SAndroid Build Coastguard Worker ContentInfo* GetFirstAudioContent(SessionDescription* sdesc) {
3127*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(sdesc, MEDIA_TYPE_AUDIO);
3128*d9f75844SAndroid Build Coastguard Worker }
3129*d9f75844SAndroid Build Coastguard Worker
GetFirstVideoContent(SessionDescription * sdesc)3130*d9f75844SAndroid Build Coastguard Worker ContentInfo* GetFirstVideoContent(SessionDescription* sdesc) {
3131*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(sdesc, MEDIA_TYPE_VIDEO);
3132*d9f75844SAndroid Build Coastguard Worker }
3133*d9f75844SAndroid Build Coastguard Worker
GetFirstDataContent(SessionDescription * sdesc)3134*d9f75844SAndroid Build Coastguard Worker ContentInfo* GetFirstDataContent(SessionDescription* sdesc) {
3135*d9f75844SAndroid Build Coastguard Worker return GetFirstMediaContent(sdesc, MEDIA_TYPE_DATA);
3136*d9f75844SAndroid Build Coastguard Worker }
3137*d9f75844SAndroid Build Coastguard Worker
GetFirstMediaContentDescription(SessionDescription * sdesc,MediaType media_type)3138*d9f75844SAndroid Build Coastguard Worker MediaContentDescription* GetFirstMediaContentDescription(
3139*d9f75844SAndroid Build Coastguard Worker SessionDescription* sdesc,
3140*d9f75844SAndroid Build Coastguard Worker MediaType media_type) {
3141*d9f75844SAndroid Build Coastguard Worker ContentInfo* content = GetFirstMediaContent(sdesc, media_type);
3142*d9f75844SAndroid Build Coastguard Worker return (content ? content->media_description() : nullptr);
3143*d9f75844SAndroid Build Coastguard Worker }
3144*d9f75844SAndroid Build Coastguard Worker
GetFirstAudioContentDescription(SessionDescription * sdesc)3145*d9f75844SAndroid Build Coastguard Worker AudioContentDescription* GetFirstAudioContentDescription(
3146*d9f75844SAndroid Build Coastguard Worker SessionDescription* sdesc) {
3147*d9f75844SAndroid Build Coastguard Worker auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO);
3148*d9f75844SAndroid Build Coastguard Worker return desc ? desc->as_audio() : nullptr;
3149*d9f75844SAndroid Build Coastguard Worker }
3150*d9f75844SAndroid Build Coastguard Worker
GetFirstVideoContentDescription(SessionDescription * sdesc)3151*d9f75844SAndroid Build Coastguard Worker VideoContentDescription* GetFirstVideoContentDescription(
3152*d9f75844SAndroid Build Coastguard Worker SessionDescription* sdesc) {
3153*d9f75844SAndroid Build Coastguard Worker auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO);
3154*d9f75844SAndroid Build Coastguard Worker return desc ? desc->as_video() : nullptr;
3155*d9f75844SAndroid Build Coastguard Worker }
3156*d9f75844SAndroid Build Coastguard Worker
GetFirstSctpDataContentDescription(SessionDescription * sdesc)3157*d9f75844SAndroid Build Coastguard Worker SctpDataContentDescription* GetFirstSctpDataContentDescription(
3158*d9f75844SAndroid Build Coastguard Worker SessionDescription* sdesc) {
3159*d9f75844SAndroid Build Coastguard Worker auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
3160*d9f75844SAndroid Build Coastguard Worker return desc ? desc->as_sctp() : nullptr;
3161*d9f75844SAndroid Build Coastguard Worker }
3162*d9f75844SAndroid Build Coastguard Worker
3163*d9f75844SAndroid Build Coastguard Worker } // namespace cricket
3164