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