xref: /aosp_15_r20/external/webrtc/media/base/media_engine.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "media/base/media_engine.h"
12 
13 #include <stddef.h>
14 
15 #include <cstdint>
16 #include <string>
17 #include <utility>
18 
19 #include "absl/algorithm/container.h"
20 #include "api/video/video_bitrate_allocation.h"
21 #include "rtc_base/checks.h"
22 #include "rtc_base/string_encode.h"
23 
24 namespace cricket {
25 
26 RtpCapabilities::RtpCapabilities() = default;
27 RtpCapabilities::~RtpCapabilities() = default;
28 
CreateRtpParametersWithOneEncoding()29 webrtc::RtpParameters CreateRtpParametersWithOneEncoding() {
30   webrtc::RtpParameters parameters;
31   webrtc::RtpEncodingParameters encoding;
32   parameters.encodings.push_back(encoding);
33   return parameters;
34 }
35 
CreateRtpParametersWithEncodings(StreamParams sp)36 webrtc::RtpParameters CreateRtpParametersWithEncodings(StreamParams sp) {
37   std::vector<uint32_t> primary_ssrcs;
38   sp.GetPrimarySsrcs(&primary_ssrcs);
39   size_t encoding_count = primary_ssrcs.size();
40 
41   std::vector<webrtc::RtpEncodingParameters> encodings(encoding_count);
42   for (size_t i = 0; i < encodings.size(); ++i) {
43     encodings[i].ssrc = primary_ssrcs[i];
44   }
45 
46   const std::vector<RidDescription>& rids = sp.rids();
47   RTC_DCHECK(rids.size() == 0 || rids.size() == encoding_count);
48   for (size_t i = 0; i < rids.size(); ++i) {
49     encodings[i].rid = rids[i].rid;
50   }
51 
52   webrtc::RtpParameters parameters;
53   parameters.encodings = encodings;
54   parameters.rtcp.cname = sp.cname;
55   return parameters;
56 }
57 
GetDefaultEnabledRtpHeaderExtensions(const RtpHeaderExtensionQueryInterface & query_interface)58 std::vector<webrtc::RtpExtension> GetDefaultEnabledRtpHeaderExtensions(
59     const RtpHeaderExtensionQueryInterface& query_interface) {
60   std::vector<webrtc::RtpExtension> extensions;
61   for (const auto& entry : query_interface.GetRtpHeaderExtensions()) {
62     if (entry.direction != webrtc::RtpTransceiverDirection::kStopped)
63       extensions.emplace_back(entry.uri, *entry.preferred_id);
64   }
65   return extensions;
66 }
67 
CheckScalabilityModeValues(const webrtc::RtpParameters & rtp_parameters,rtc::ArrayView<cricket::VideoCodec> codecs)68 webrtc::RTCError CheckScalabilityModeValues(
69     const webrtc::RtpParameters& rtp_parameters,
70     rtc::ArrayView<cricket::VideoCodec> codecs) {
71   using webrtc::RTCErrorType;
72 
73   if (codecs.empty()) {
74     // This is an audio sender or an extra check in the stack where the codec
75     // list is not available and we can't check the scalability_mode values.
76     return webrtc::RTCError::OK();
77   }
78 
79   for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
80     if (rtp_parameters.encodings[i].scalability_mode) {
81       bool scalabilityModeFound = false;
82       for (const cricket::VideoCodec& codec : codecs) {
83         for (const auto& scalability_mode : codec.scalability_modes) {
84           if (ScalabilityModeToString(scalability_mode) ==
85               *rtp_parameters.encodings[i].scalability_mode) {
86             scalabilityModeFound = true;
87             break;
88           }
89         }
90         if (scalabilityModeFound)
91           break;
92       }
93 
94       if (!scalabilityModeFound) {
95         LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
96                              "Attempted to set RtpParameters scalabilityMode "
97                              "to an unsupported value for the current codecs.");
98       }
99     }
100   }
101 
102   return webrtc::RTCError::OK();
103 }
104 
CheckRtpParametersValues(const webrtc::RtpParameters & rtp_parameters,rtc::ArrayView<cricket::VideoCodec> codecs)105 webrtc::RTCError CheckRtpParametersValues(
106     const webrtc::RtpParameters& rtp_parameters,
107     rtc::ArrayView<cricket::VideoCodec> codecs) {
108   using webrtc::RTCErrorType;
109 
110   for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
111     if (rtp_parameters.encodings[i].bitrate_priority <= 0) {
112       LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
113                            "Attempted to set RtpParameters bitrate_priority to "
114                            "an invalid number. bitrate_priority must be > 0.");
115     }
116     if (rtp_parameters.encodings[i].scale_resolution_down_by &&
117         *rtp_parameters.encodings[i].scale_resolution_down_by < 1.0) {
118       LOG_AND_RETURN_ERROR(
119           RTCErrorType::INVALID_RANGE,
120           "Attempted to set RtpParameters scale_resolution_down_by to an "
121           "invalid value. scale_resolution_down_by must be >= 1.0");
122     }
123     if (rtp_parameters.encodings[i].max_framerate &&
124         *rtp_parameters.encodings[i].max_framerate < 0.0) {
125       LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
126                            "Attempted to set RtpParameters max_framerate to an "
127                            "invalid value. max_framerate must be >= 0.0");
128     }
129     if (rtp_parameters.encodings[i].min_bitrate_bps &&
130         rtp_parameters.encodings[i].max_bitrate_bps) {
131       if (*rtp_parameters.encodings[i].max_bitrate_bps <
132           *rtp_parameters.encodings[i].min_bitrate_bps) {
133         LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::INVALID_RANGE,
134                              "Attempted to set RtpParameters min bitrate "
135                              "larger than max bitrate.");
136       }
137     }
138     if (rtp_parameters.encodings[i].num_temporal_layers) {
139       if (*rtp_parameters.encodings[i].num_temporal_layers < 1 ||
140           *rtp_parameters.encodings[i].num_temporal_layers >
141               webrtc::kMaxTemporalStreams) {
142         LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
143                              "Attempted to set RtpParameters "
144                              "num_temporal_layers to an invalid number.");
145       }
146     }
147 
148     if (rtp_parameters.encodings[i].requested_resolution &&
149         rtp_parameters.encodings[i].scale_resolution_down_by) {
150       LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
151                            "Attempted to set scale_resolution_down_by and "
152                            "requested_resolution simultaniously.");
153     }
154   }
155 
156   return CheckScalabilityModeValues(rtp_parameters, codecs);
157 }
158 
CheckRtpParametersInvalidModificationAndValues(const webrtc::RtpParameters & old_rtp_parameters,const webrtc::RtpParameters & rtp_parameters)159 webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
160     const webrtc::RtpParameters& old_rtp_parameters,
161     const webrtc::RtpParameters& rtp_parameters) {
162   return CheckRtpParametersInvalidModificationAndValues(old_rtp_parameters,
163                                                         rtp_parameters, {});
164 }
165 
CheckRtpParametersInvalidModificationAndValues(const webrtc::RtpParameters & old_rtp_parameters,const webrtc::RtpParameters & rtp_parameters,rtc::ArrayView<cricket::VideoCodec> codecs)166 webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
167     const webrtc::RtpParameters& old_rtp_parameters,
168     const webrtc::RtpParameters& rtp_parameters,
169     rtc::ArrayView<cricket::VideoCodec> codecs) {
170   using webrtc::RTCErrorType;
171   if (rtp_parameters.encodings.size() != old_rtp_parameters.encodings.size()) {
172     LOG_AND_RETURN_ERROR(
173         RTCErrorType::INVALID_MODIFICATION,
174         "Attempted to set RtpParameters with different encoding count");
175   }
176   if (rtp_parameters.rtcp != old_rtp_parameters.rtcp) {
177     LOG_AND_RETURN_ERROR(
178         RTCErrorType::INVALID_MODIFICATION,
179         "Attempted to set RtpParameters with modified RTCP parameters");
180   }
181   if (rtp_parameters.header_extensions !=
182       old_rtp_parameters.header_extensions) {
183     LOG_AND_RETURN_ERROR(
184         RTCErrorType::INVALID_MODIFICATION,
185         "Attempted to set RtpParameters with modified header extensions");
186   }
187   if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
188                      [](const webrtc::RtpEncodingParameters& encoding1,
189                         const webrtc::RtpEncodingParameters& encoding2) {
190                        return encoding1.rid == encoding2.rid;
191                      })) {
192     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
193                          "Attempted to change RID values in the encodings.");
194   }
195   if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
196                      [](const webrtc::RtpEncodingParameters& encoding1,
197                         const webrtc::RtpEncodingParameters& encoding2) {
198                        return encoding1.ssrc == encoding2.ssrc;
199                      })) {
200     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
201                          "Attempted to set RtpParameters with modified SSRC");
202   }
203 
204   return CheckRtpParametersValues(rtp_parameters, codecs);
205 }
206 
CompositeMediaEngine(std::unique_ptr<webrtc::FieldTrialsView> trials,std::unique_ptr<VoiceEngineInterface> audio_engine,std::unique_ptr<VideoEngineInterface> video_engine)207 CompositeMediaEngine::CompositeMediaEngine(
208     std::unique_ptr<webrtc::FieldTrialsView> trials,
209     std::unique_ptr<VoiceEngineInterface> audio_engine,
210     std::unique_ptr<VideoEngineInterface> video_engine)
211     : trials_(std::move(trials)),
212       voice_engine_(std::move(audio_engine)),
213       video_engine_(std::move(video_engine)) {}
214 
CompositeMediaEngine(std::unique_ptr<VoiceEngineInterface> audio_engine,std::unique_ptr<VideoEngineInterface> video_engine)215 CompositeMediaEngine::CompositeMediaEngine(
216     std::unique_ptr<VoiceEngineInterface> audio_engine,
217     std::unique_ptr<VideoEngineInterface> video_engine)
218     : CompositeMediaEngine(nullptr,
219                            std::move(audio_engine),
220                            std::move(video_engine)) {}
221 
222 CompositeMediaEngine::~CompositeMediaEngine() = default;
223 
Init()224 bool CompositeMediaEngine::Init() {
225   voice().Init();
226   return true;
227 }
228 
voice()229 VoiceEngineInterface& CompositeMediaEngine::voice() {
230   return *voice_engine_.get();
231 }
232 
video()233 VideoEngineInterface& CompositeMediaEngine::video() {
234   return *video_engine_.get();
235 }
236 
voice() const237 const VoiceEngineInterface& CompositeMediaEngine::voice() const {
238   return *voice_engine_.get();
239 }
240 
video() const241 const VideoEngineInterface& CompositeMediaEngine::video() const {
242   return *video_engine_.get();
243 }
244 
245 }  // namespace cricket
246