xref: /aosp_15_r20/external/webrtc/media/engine/webrtc_media_engine.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2014 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 "media/engine/webrtc_media_engine.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker #include <map>
15*d9f75844SAndroid Build Coastguard Worker #include <memory>
16*d9f75844SAndroid Build Coastguard Worker #include <string>
17*d9f75844SAndroid Build Coastguard Worker #include <utility>
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
20*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/match.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/transport/field_trial_based_config.h"
22*d9f75844SAndroid Build Coastguard Worker #include "media/base/media_constants.h"
23*d9f75844SAndroid Build Coastguard Worker #include "media/engine/webrtc_voice_engine.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
26*d9f75844SAndroid Build Coastguard Worker 
27*d9f75844SAndroid Build Coastguard Worker #ifdef HAVE_WEBRTC_VIDEO
28*d9f75844SAndroid Build Coastguard Worker #include "media/engine/webrtc_video_engine.h"
29*d9f75844SAndroid Build Coastguard Worker #else
30*d9f75844SAndroid Build Coastguard Worker #include "media/engine/null_webrtc_video_engine.h"
31*d9f75844SAndroid Build Coastguard Worker #endif
32*d9f75844SAndroid Build Coastguard Worker 
33*d9f75844SAndroid Build Coastguard Worker namespace cricket {
34*d9f75844SAndroid Build Coastguard Worker 
CreateMediaEngine(MediaEngineDependencies dependencies)35*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<MediaEngineInterface> CreateMediaEngine(
36*d9f75844SAndroid Build Coastguard Worker     MediaEngineDependencies dependencies) {
37*d9f75844SAndroid Build Coastguard Worker   // TODO(sprang): Make populating `dependencies.trials` mandatory and remove
38*d9f75844SAndroid Build Coastguard Worker   // these fallbacks.
39*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<webrtc::FieldTrialsView> fallback_trials(
40*d9f75844SAndroid Build Coastguard Worker       dependencies.trials ? nullptr : new webrtc::FieldTrialBasedConfig());
41*d9f75844SAndroid Build Coastguard Worker   const webrtc::FieldTrialsView& trials =
42*d9f75844SAndroid Build Coastguard Worker       dependencies.trials ? *dependencies.trials : *fallback_trials;
43*d9f75844SAndroid Build Coastguard Worker   auto audio_engine = std::make_unique<WebRtcVoiceEngine>(
44*d9f75844SAndroid Build Coastguard Worker       dependencies.task_queue_factory, dependencies.adm.get(),
45*d9f75844SAndroid Build Coastguard Worker       std::move(dependencies.audio_encoder_factory),
46*d9f75844SAndroid Build Coastguard Worker       std::move(dependencies.audio_decoder_factory),
47*d9f75844SAndroid Build Coastguard Worker       std::move(dependencies.audio_mixer),
48*d9f75844SAndroid Build Coastguard Worker       std::move(dependencies.audio_processing),
49*d9f75844SAndroid Build Coastguard Worker       dependencies.audio_frame_processor, trials);
50*d9f75844SAndroid Build Coastguard Worker #ifdef HAVE_WEBRTC_VIDEO
51*d9f75844SAndroid Build Coastguard Worker   auto video_engine = std::make_unique<WebRtcVideoEngine>(
52*d9f75844SAndroid Build Coastguard Worker       std::move(dependencies.video_encoder_factory),
53*d9f75844SAndroid Build Coastguard Worker       std::move(dependencies.video_decoder_factory), trials);
54*d9f75844SAndroid Build Coastguard Worker #else
55*d9f75844SAndroid Build Coastguard Worker   auto video_engine = std::make_unique<NullWebRtcVideoEngine>();
56*d9f75844SAndroid Build Coastguard Worker #endif
57*d9f75844SAndroid Build Coastguard Worker   return std::make_unique<CompositeMediaEngine>(std::move(fallback_trials),
58*d9f75844SAndroid Build Coastguard Worker                                                 std::move(audio_engine),
59*d9f75844SAndroid Build Coastguard Worker                                                 std::move(video_engine));
60*d9f75844SAndroid Build Coastguard Worker }
61*d9f75844SAndroid Build Coastguard Worker 
62*d9f75844SAndroid Build Coastguard Worker namespace {
63*d9f75844SAndroid Build Coastguard Worker // Remove mutually exclusive extensions with lower priority.
DiscardRedundantExtensions(std::vector<webrtc::RtpExtension> * extensions,rtc::ArrayView<const char * const> extensions_decreasing_prio)64*d9f75844SAndroid Build Coastguard Worker void DiscardRedundantExtensions(
65*d9f75844SAndroid Build Coastguard Worker     std::vector<webrtc::RtpExtension>* extensions,
66*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const char* const> extensions_decreasing_prio) {
67*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(extensions);
68*d9f75844SAndroid Build Coastguard Worker   bool found = false;
69*d9f75844SAndroid Build Coastguard Worker   for (const char* uri : extensions_decreasing_prio) {
70*d9f75844SAndroid Build Coastguard Worker     auto it = absl::c_find_if(
71*d9f75844SAndroid Build Coastguard Worker         *extensions,
72*d9f75844SAndroid Build Coastguard Worker         [uri](const webrtc::RtpExtension& rhs) { return rhs.uri == uri; });
73*d9f75844SAndroid Build Coastguard Worker     if (it != extensions->end()) {
74*d9f75844SAndroid Build Coastguard Worker       if (found) {
75*d9f75844SAndroid Build Coastguard Worker         extensions->erase(it);
76*d9f75844SAndroid Build Coastguard Worker       }
77*d9f75844SAndroid Build Coastguard Worker       found = true;
78*d9f75844SAndroid Build Coastguard Worker     }
79*d9f75844SAndroid Build Coastguard Worker   }
80*d9f75844SAndroid Build Coastguard Worker }
81*d9f75844SAndroid Build Coastguard Worker }  // namespace
82*d9f75844SAndroid Build Coastguard Worker 
ValidateRtpExtensions(rtc::ArrayView<const webrtc::RtpExtension> extensions,rtc::ArrayView<const webrtc::RtpExtension> old_extensions)83*d9f75844SAndroid Build Coastguard Worker bool ValidateRtpExtensions(
84*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const webrtc::RtpExtension> extensions,
85*d9f75844SAndroid Build Coastguard Worker     rtc::ArrayView<const webrtc::RtpExtension> old_extensions) {
86*d9f75844SAndroid Build Coastguard Worker   bool id_used[1 + webrtc::RtpExtension::kMaxId] = {false};
87*d9f75844SAndroid Build Coastguard Worker   for (const auto& extension : extensions) {
88*d9f75844SAndroid Build Coastguard Worker     if (extension.id < webrtc::RtpExtension::kMinId ||
89*d9f75844SAndroid Build Coastguard Worker         extension.id > webrtc::RtpExtension::kMaxId) {
90*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString();
91*d9f75844SAndroid Build Coastguard Worker       return false;
92*d9f75844SAndroid Build Coastguard Worker     }
93*d9f75844SAndroid Build Coastguard Worker     if (id_used[extension.id]) {
94*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << "Duplicate RTP extension ID: "
95*d9f75844SAndroid Build Coastguard Worker                         << extension.ToString();
96*d9f75844SAndroid Build Coastguard Worker       return false;
97*d9f75844SAndroid Build Coastguard Worker     }
98*d9f75844SAndroid Build Coastguard Worker     id_used[extension.id] = true;
99*d9f75844SAndroid Build Coastguard Worker   }
100*d9f75844SAndroid Build Coastguard Worker   // Validate the extension list against the already negotiated extensions.
101*d9f75844SAndroid Build Coastguard Worker   // Re-registering is OK, re-mapping (either same URL at new ID or same
102*d9f75844SAndroid Build Coastguard Worker   // ID used with new URL) is an illegal remap.
103*d9f75844SAndroid Build Coastguard Worker 
104*d9f75844SAndroid Build Coastguard Worker   // This is required in order to avoid a crash when registering an
105*d9f75844SAndroid Build Coastguard Worker   // extension. A better structure would use the registered extensions
106*d9f75844SAndroid Build Coastguard Worker   // in the RTPSender. This requires spinning through:
107*d9f75844SAndroid Build Coastguard Worker   //
108*d9f75844SAndroid Build Coastguard Worker   // WebRtcVoiceMediaChannel::::WebRtcAudioSendStream::stream_ (pointer)
109*d9f75844SAndroid Build Coastguard Worker   // AudioSendStream::rtp_rtcp_module_ (pointer)
110*d9f75844SAndroid Build Coastguard Worker   // ModuleRtpRtcpImpl2::rtp_sender_ (pointer)
111*d9f75844SAndroid Build Coastguard Worker   // RtpSenderContext::packet_generator (struct member)
112*d9f75844SAndroid Build Coastguard Worker   // RTPSender::rtp_header_extension_map_ (class member)
113*d9f75844SAndroid Build Coastguard Worker   //
114*d9f75844SAndroid Build Coastguard Worker   // Getting at this seems like a hard slog.
115*d9f75844SAndroid Build Coastguard Worker   if (!old_extensions.empty()) {
116*d9f75844SAndroid Build Coastguard Worker     absl::string_view urimap[1 + webrtc::RtpExtension::kMaxId];
117*d9f75844SAndroid Build Coastguard Worker     std::map<absl::string_view, int> idmap;
118*d9f75844SAndroid Build Coastguard Worker     for (const auto& old_extension : old_extensions) {
119*d9f75844SAndroid Build Coastguard Worker       urimap[old_extension.id] = old_extension.uri;
120*d9f75844SAndroid Build Coastguard Worker       idmap[old_extension.uri] = old_extension.id;
121*d9f75844SAndroid Build Coastguard Worker     }
122*d9f75844SAndroid Build Coastguard Worker     for (const auto& extension : extensions) {
123*d9f75844SAndroid Build Coastguard Worker       if (!urimap[extension.id].empty() &&
124*d9f75844SAndroid Build Coastguard Worker           urimap[extension.id] != extension.uri) {
125*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_ERROR) << "Extension negotiation failure: " << extension.id
126*d9f75844SAndroid Build Coastguard Worker                           << " was mapped to " << urimap[extension.id]
127*d9f75844SAndroid Build Coastguard Worker                           << " but is proposed changed to " << extension.uri;
128*d9f75844SAndroid Build Coastguard Worker         return false;
129*d9f75844SAndroid Build Coastguard Worker       }
130*d9f75844SAndroid Build Coastguard Worker       const auto& it = idmap.find(extension.uri);
131*d9f75844SAndroid Build Coastguard Worker       if (it != idmap.end() && it->second != extension.id) {
132*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_ERROR) << "Extension negotation failure: " << extension.uri
133*d9f75844SAndroid Build Coastguard Worker                           << " was identified by " << it->second
134*d9f75844SAndroid Build Coastguard Worker                           << " but is proposed changed to " << extension.id;
135*d9f75844SAndroid Build Coastguard Worker         return false;
136*d9f75844SAndroid Build Coastguard Worker       }
137*d9f75844SAndroid Build Coastguard Worker     }
138*d9f75844SAndroid Build Coastguard Worker   }
139*d9f75844SAndroid Build Coastguard Worker   return true;
140*d9f75844SAndroid Build Coastguard Worker }
141*d9f75844SAndroid Build Coastguard Worker 
FilterRtpExtensions(const std::vector<webrtc::RtpExtension> & extensions,bool (* supported)(absl::string_view),bool filter_redundant_extensions,const webrtc::FieldTrialsView & trials)142*d9f75844SAndroid Build Coastguard Worker std::vector<webrtc::RtpExtension> FilterRtpExtensions(
143*d9f75844SAndroid Build Coastguard Worker     const std::vector<webrtc::RtpExtension>& extensions,
144*d9f75844SAndroid Build Coastguard Worker     bool (*supported)(absl::string_view),
145*d9f75844SAndroid Build Coastguard Worker     bool filter_redundant_extensions,
146*d9f75844SAndroid Build Coastguard Worker     const webrtc::FieldTrialsView& trials) {
147*d9f75844SAndroid Build Coastguard Worker   // Don't check against old parameters; this should have been done earlier.
148*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(ValidateRtpExtensions(extensions, {}));
149*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(supported);
150*d9f75844SAndroid Build Coastguard Worker   std::vector<webrtc::RtpExtension> result;
151*d9f75844SAndroid Build Coastguard Worker 
152*d9f75844SAndroid Build Coastguard Worker   // Ignore any extensions that we don't recognize.
153*d9f75844SAndroid Build Coastguard Worker   for (const auto& extension : extensions) {
154*d9f75844SAndroid Build Coastguard Worker     if (supported(extension.uri)) {
155*d9f75844SAndroid Build Coastguard Worker       result.push_back(extension);
156*d9f75844SAndroid Build Coastguard Worker     } else {
157*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "Unsupported RTP extension: "
158*d9f75844SAndroid Build Coastguard Worker                           << extension.ToString();
159*d9f75844SAndroid Build Coastguard Worker     }
160*d9f75844SAndroid Build Coastguard Worker   }
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker   // Sort by name, ascending (prioritise encryption), so that we don't reset
163*d9f75844SAndroid Build Coastguard Worker   // extensions if they were specified in a different order (also allows us
164*d9f75844SAndroid Build Coastguard Worker   // to use std::unique below).
165*d9f75844SAndroid Build Coastguard Worker   absl::c_sort(result, [](const webrtc::RtpExtension& rhs,
166*d9f75844SAndroid Build Coastguard Worker                           const webrtc::RtpExtension& lhs) {
167*d9f75844SAndroid Build Coastguard Worker     return rhs.encrypt == lhs.encrypt ? rhs.uri < lhs.uri
168*d9f75844SAndroid Build Coastguard Worker                                       : rhs.encrypt > lhs.encrypt;
169*d9f75844SAndroid Build Coastguard Worker   });
170*d9f75844SAndroid Build Coastguard Worker 
171*d9f75844SAndroid Build Coastguard Worker   // Remove unnecessary extensions (used on send side).
172*d9f75844SAndroid Build Coastguard Worker   if (filter_redundant_extensions) {
173*d9f75844SAndroid Build Coastguard Worker     auto it = std::unique(
174*d9f75844SAndroid Build Coastguard Worker         result.begin(), result.end(),
175*d9f75844SAndroid Build Coastguard Worker         [](const webrtc::RtpExtension& rhs, const webrtc::RtpExtension& lhs) {
176*d9f75844SAndroid Build Coastguard Worker           return rhs.uri == lhs.uri && rhs.encrypt == lhs.encrypt;
177*d9f75844SAndroid Build Coastguard Worker         });
178*d9f75844SAndroid Build Coastguard Worker     result.erase(it, result.end());
179*d9f75844SAndroid Build Coastguard Worker 
180*d9f75844SAndroid Build Coastguard Worker     // Keep just the highest priority extension of any in the following lists.
181*d9f75844SAndroid Build Coastguard Worker     if (absl::StartsWith(trials.Lookup("WebRTC-FilterAbsSendTimeExtension"),
182*d9f75844SAndroid Build Coastguard Worker                          "Enabled")) {
183*d9f75844SAndroid Build Coastguard Worker       static const char* const kBweExtensionPriorities[] = {
184*d9f75844SAndroid Build Coastguard Worker           webrtc::RtpExtension::kTransportSequenceNumberUri,
185*d9f75844SAndroid Build Coastguard Worker           webrtc::RtpExtension::kAbsSendTimeUri,
186*d9f75844SAndroid Build Coastguard Worker           webrtc::RtpExtension::kTimestampOffsetUri};
187*d9f75844SAndroid Build Coastguard Worker       DiscardRedundantExtensions(&result, kBweExtensionPriorities);
188*d9f75844SAndroid Build Coastguard Worker     } else {
189*d9f75844SAndroid Build Coastguard Worker       static const char* const kBweExtensionPriorities[] = {
190*d9f75844SAndroid Build Coastguard Worker           webrtc::RtpExtension::kAbsSendTimeUri,
191*d9f75844SAndroid Build Coastguard Worker           webrtc::RtpExtension::kTimestampOffsetUri};
192*d9f75844SAndroid Build Coastguard Worker       DiscardRedundantExtensions(&result, kBweExtensionPriorities);
193*d9f75844SAndroid Build Coastguard Worker     }
194*d9f75844SAndroid Build Coastguard Worker   }
195*d9f75844SAndroid Build Coastguard Worker   return result;
196*d9f75844SAndroid Build Coastguard Worker }
197*d9f75844SAndroid Build Coastguard Worker 
GetBitrateConfigForCodec(const Codec & codec)198*d9f75844SAndroid Build Coastguard Worker webrtc::BitrateConstraints GetBitrateConfigForCodec(const Codec& codec) {
199*d9f75844SAndroid Build Coastguard Worker   webrtc::BitrateConstraints config;
200*d9f75844SAndroid Build Coastguard Worker   int bitrate_kbps = 0;
201*d9f75844SAndroid Build Coastguard Worker   if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
202*d9f75844SAndroid Build Coastguard Worker       bitrate_kbps > 0) {
203*d9f75844SAndroid Build Coastguard Worker     config.min_bitrate_bps = bitrate_kbps * 1000;
204*d9f75844SAndroid Build Coastguard Worker   } else {
205*d9f75844SAndroid Build Coastguard Worker     config.min_bitrate_bps = 0;
206*d9f75844SAndroid Build Coastguard Worker   }
207*d9f75844SAndroid Build Coastguard Worker   if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
208*d9f75844SAndroid Build Coastguard Worker       bitrate_kbps > 0) {
209*d9f75844SAndroid Build Coastguard Worker     config.start_bitrate_bps = bitrate_kbps * 1000;
210*d9f75844SAndroid Build Coastguard Worker   } else {
211*d9f75844SAndroid Build Coastguard Worker     // Do not reconfigure start bitrate unless it's specified and positive.
212*d9f75844SAndroid Build Coastguard Worker     config.start_bitrate_bps = -1;
213*d9f75844SAndroid Build Coastguard Worker   }
214*d9f75844SAndroid Build Coastguard Worker   if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
215*d9f75844SAndroid Build Coastguard Worker       bitrate_kbps > 0) {
216*d9f75844SAndroid Build Coastguard Worker     config.max_bitrate_bps = bitrate_kbps * 1000;
217*d9f75844SAndroid Build Coastguard Worker   } else {
218*d9f75844SAndroid Build Coastguard Worker     config.max_bitrate_bps = -1;
219*d9f75844SAndroid Build Coastguard Worker   }
220*d9f75844SAndroid Build Coastguard Worker   return config;
221*d9f75844SAndroid Build Coastguard Worker }
222*d9f75844SAndroid Build Coastguard Worker }  // namespace cricket
223