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