blob: 7304ab03d75599c2db3451e794efdb0f6de34dff [file] [log] [blame]
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:131/*
kjellander1afca732016-02-08 04:46:452 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved.
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:133 *
kjellander1afca732016-02-08 04:46:454 * 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.
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:139 */
henrike@webrtc.org28e20752013-07-10 00:45:3610
Steve Anton10542f22019-01-11 17:11:0011#include "media/base/media_engine.h"
henrike@webrtc.org28e20752013-07-10 00:45:3612
Yves Gerey3e707812018-11-28 15:47:4913#include <stddef.h>
Jonas Olssona4d87372019-07-05 17:08:3314
Yves Gerey3e707812018-11-28 15:47:4915#include <cstdint>
16#include <string>
Sebastian Janssonfa0aa392018-11-16 08:54:3217#include <utility>
18
Amit Hilbuch2297d332019-02-19 20:49:2219#include "absl/algorithm/container.h"
Åsa Persson23eba222018-10-02 12:47:0620#include "api/video/video_bitrate_allocation.h"
Yves Gerey3e707812018-11-28 15:47:4921#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 17:11:0022#include "rtc_base/string_encode.h"
Åsa Persson23eba222018-10-02 12:47:0623
skvladdc1c62c2016-03-17 02:07:4324namespace cricket {
25
Paulina Hensman11b34f42018-04-09 12:24:5226RtpCapabilities::RtpCapabilities() = default;
27RtpCapabilities::~RtpCapabilities() = default;
28
skvladdc1c62c2016-03-17 02:07:4329webrtc::RtpParameters CreateRtpParametersWithOneEncoding() {
30 webrtc::RtpParameters parameters;
31 webrtc::RtpEncodingParameters encoding;
32 parameters.encodings.push_back(encoding);
33 return parameters;
34}
35
Zach Stein3ca452b2018-01-18 18:01:2436webrtc::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 }
Amit Hilbuch2297d332019-02-19 20:49:2245
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
Zach Stein3ca452b2018-01-18 18:01:2452 webrtc::RtpParameters parameters;
53 parameters.encodings = encodings;
Florent Castellidacec712018-05-24 14:24:2154 parameters.rtcp.cname = sp.cname;
Zach Stein3ca452b2018-01-18 18:01:2455 return parameters;
56}
57
Markus Handell0357b3e2020-03-16 12:40:5158std::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
Florent Castelli725ee242022-10-18 15:05:5868webrtc::RTCError CheckScalabilityModeValues(
69 const webrtc::RtpParameters& rtp_parameters,
Henrik Boström1e7a6f32024-02-13 08:22:2070 rtc::ArrayView<cricket::Codec> codec_preferences,
Florent Castelli43a5dd82023-04-12 10:45:0771 absl::optional<cricket::Codec> send_codec) {
Florent Castelli725ee242022-10-18 15:05:5872 using webrtc::RTCErrorType;
73
Henrik Boström1e7a6f32024-02-13 08:22:2074 if (codec_preferences.empty()) {
Florent Castelli725ee242022-10-18 15:05:5875 // This is an audio sender or an extra check in the stack where the codec
76 // list is not available and we can't check the scalability_mode values.
77 return webrtc::RTCError::OK();
78 }
79
80 for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
Florent Castelli43a5dd82023-04-12 10:45:0781 if (rtp_parameters.encodings[i].codec) {
82 bool codecFound = false;
Henrik Boström1e7a6f32024-02-13 08:22:2083 for (const cricket::VideoCodec& codec : codec_preferences) {
Florent Castelli43a5dd82023-04-12 10:45:0784 if (codec.MatchesRtpCodec(*rtp_parameters.encodings[i].codec)) {
85 codecFound = true;
86 send_codec = codec;
87 break;
88 }
89 }
90 if (!codecFound) {
91 LOG_AND_RETURN_ERROR(
92 RTCErrorType::INVALID_MODIFICATION,
93 "Attempted to use an unsupported codec for layer " +
94 std::to_string(i));
95 }
96 }
Florent Castelli725ee242022-10-18 15:05:5897 if (rtp_parameters.encodings[i].scalability_mode) {
Florent Castelli43a5dd82023-04-12 10:45:0798 if (!send_codec) {
99 bool scalabilityModeFound = false;
Henrik Boström1e7a6f32024-02-13 08:22:20100 for (const cricket::VideoCodec& codec : codec_preferences) {
Florent Castelli43a5dd82023-04-12 10:45:07101 for (const auto& scalability_mode : codec.scalability_modes) {
102 if (ScalabilityModeToString(scalability_mode) ==
103 *rtp_parameters.encodings[i].scalability_mode) {
104 scalabilityModeFound = true;
105 break;
106 }
107 }
108 if (scalabilityModeFound)
109 break;
110 }
111
112 if (!scalabilityModeFound) {
113 LOG_AND_RETURN_ERROR(
114 RTCErrorType::INVALID_MODIFICATION,
115 "Attempted to set RtpParameters scalabilityMode "
116 "to an unsupported value for the current codecs.");
117 }
118 } else {
119 bool scalabilityModeFound = false;
120 for (const auto& scalability_mode : send_codec->scalability_modes) {
Florent Castelli725ee242022-10-18 15:05:58121 if (ScalabilityModeToString(scalability_mode) ==
122 *rtp_parameters.encodings[i].scalability_mode) {
123 scalabilityModeFound = true;
124 break;
125 }
126 }
Florent Castelli43a5dd82023-04-12 10:45:07127 if (!scalabilityModeFound) {
128 LOG_AND_RETURN_ERROR(
129 RTCErrorType::INVALID_MODIFICATION,
130 "Attempted to set RtpParameters scalabilityMode "
131 "to an unsupported value for the current codecs.");
132 }
Florent Castelli725ee242022-10-18 15:05:58133 }
134 }
135 }
136
137 return webrtc::RTCError::OK();
138}
139
Florent Castellic1a0bcb2019-01-29 13:26:48140webrtc::RTCError CheckRtpParametersValues(
Florent Castelli725ee242022-10-18 15:05:58141 const webrtc::RtpParameters& rtp_parameters,
Henrik Boström1e7a6f32024-02-13 08:22:20142 rtc::ArrayView<cricket::Codec> codec_preferences,
Florent Castelli43a5dd82023-04-12 10:45:07143 absl::optional<cricket::Codec> send_codec) {
Florent Castelli892acf02018-10-01 20:47:20144 using webrtc::RTCErrorType;
Florent Castelli892acf02018-10-01 20:47:20145
146 for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
Florent Castelli892acf02018-10-01 20:47:20147 if (rtp_parameters.encodings[i].bitrate_priority <= 0) {
148 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
149 "Attempted to set RtpParameters bitrate_priority to "
150 "an invalid number. bitrate_priority must be > 0.");
151 }
Florent Castellic1a0bcb2019-01-29 13:26:48152 if (rtp_parameters.encodings[i].scale_resolution_down_by &&
153 *rtp_parameters.encodings[i].scale_resolution_down_by < 1.0) {
154 LOG_AND_RETURN_ERROR(
155 RTCErrorType::INVALID_RANGE,
156 "Attempted to set RtpParameters scale_resolution_down_by to an "
Florent Castelli907dc802019-12-06 14:03:19157 "invalid value. scale_resolution_down_by must be >= 1.0");
158 }
159 if (rtp_parameters.encodings[i].max_framerate &&
160 *rtp_parameters.encodings[i].max_framerate < 0.0) {
161 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
162 "Attempted to set RtpParameters max_framerate to an "
163 "invalid value. max_framerate must be >= 0.0");
Florent Castellic1a0bcb2019-01-29 13:26:48164 }
Florent Castelli892acf02018-10-01 20:47:20165 if (rtp_parameters.encodings[i].min_bitrate_bps &&
166 rtp_parameters.encodings[i].max_bitrate_bps) {
167 if (*rtp_parameters.encodings[i].max_bitrate_bps <
168 *rtp_parameters.encodings[i].min_bitrate_bps) {
169 LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::INVALID_RANGE,
170 "Attempted to set RtpParameters min bitrate "
171 "larger than max bitrate.");
172 }
173 }
Åsa Persson23eba222018-10-02 12:47:06174 if (rtp_parameters.encodings[i].num_temporal_layers) {
175 if (*rtp_parameters.encodings[i].num_temporal_layers < 1 ||
176 *rtp_parameters.encodings[i].num_temporal_layers >
177 webrtc::kMaxTemporalStreams) {
178 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
179 "Attempted to set RtpParameters "
180 "num_temporal_layers to an invalid number.");
181 }
182 }
Jonas Oreland0deda152022-09-23 10:08:57183
184 if (rtp_parameters.encodings[i].requested_resolution &&
185 rtp_parameters.encodings[i].scale_resolution_down_by) {
186 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
187 "Attempted to set scale_resolution_down_by and "
188 "requested_resolution simultaniously.");
189 }
Florent Castelli43a5dd82023-04-12 10:45:07190
191 if (i > 0 && rtp_parameters.encodings[i - 1].codec !=
192 rtp_parameters.encodings[i].codec) {
193 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
194 "Attempted to use different codec values for "
195 "different encodings.");
196 }
Florent Castelli892acf02018-10-01 20:47:20197 }
Florent Castellic1a0bcb2019-01-29 13:26:48198
Henrik Boström1e7a6f32024-02-13 08:22:20199 return CheckScalabilityModeValues(rtp_parameters, codec_preferences,
200 send_codec);
Florent Castelli892acf02018-10-01 20:47:20201}
202
Florent Castellic1a0bcb2019-01-29 13:26:48203webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
204 const webrtc::RtpParameters& old_rtp_parameters,
205 const webrtc::RtpParameters& rtp_parameters) {
Florent Castelli43a5dd82023-04-12 10:45:07206 return CheckRtpParametersInvalidModificationAndValues(
207 old_rtp_parameters, rtp_parameters, {}, absl::nullopt);
Florent Castelli725ee242022-10-18 15:05:58208}
209
210webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
211 const webrtc::RtpParameters& old_rtp_parameters,
212 const webrtc::RtpParameters& rtp_parameters,
Henrik Boström1e7a6f32024-02-13 08:22:20213 rtc::ArrayView<cricket::Codec> codec_preferences,
Florent Castelli43a5dd82023-04-12 10:45:07214 absl::optional<cricket::Codec> send_codec) {
Florent Castellic1a0bcb2019-01-29 13:26:48215 using webrtc::RTCErrorType;
216 if (rtp_parameters.encodings.size() != old_rtp_parameters.encodings.size()) {
217 LOG_AND_RETURN_ERROR(
218 RTCErrorType::INVALID_MODIFICATION,
219 "Attempted to set RtpParameters with different encoding count");
220 }
221 if (rtp_parameters.rtcp != old_rtp_parameters.rtcp) {
222 LOG_AND_RETURN_ERROR(
223 RTCErrorType::INVALID_MODIFICATION,
224 "Attempted to set RtpParameters with modified RTCP parameters");
225 }
226 if (rtp_parameters.header_extensions !=
227 old_rtp_parameters.header_extensions) {
228 LOG_AND_RETURN_ERROR(
229 RTCErrorType::INVALID_MODIFICATION,
230 "Attempted to set RtpParameters with modified header extensions");
231 }
Amit Hilbuch2297d332019-02-19 20:49:22232 if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
233 [](const webrtc::RtpEncodingParameters& encoding1,
234 const webrtc::RtpEncodingParameters& encoding2) {
235 return encoding1.rid == encoding2.rid;
236 })) {
237 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
238 "Attempted to change RID values in the encodings.");
239 }
240 if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
241 [](const webrtc::RtpEncodingParameters& encoding1,
242 const webrtc::RtpEncodingParameters& encoding2) {
243 return encoding1.ssrc == encoding2.ssrc;
244 })) {
245 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
246 "Attempted to set RtpParameters with modified SSRC");
Florent Castellic1a0bcb2019-01-29 13:26:48247 }
248
Henrik Boström1e7a6f32024-02-13 08:22:20249 return CheckRtpParametersValues(rtp_parameters, codec_preferences,
250 send_codec);
Florent Castellic1a0bcb2019-01-29 13:26:48251}
252
Sebastian Janssonfa0aa392018-11-16 08:54:32253CompositeMediaEngine::CompositeMediaEngine(
Jonas Orelande62c2f22022-03-29 09:04:48254 std::unique_ptr<webrtc::FieldTrialsView> trials,
Erik Språngceb44952020-09-22 09:36:35255 std::unique_ptr<VoiceEngineInterface> audio_engine,
Sebastian Janssonfa0aa392018-11-16 08:54:32256 std::unique_ptr<VideoEngineInterface> video_engine)
Erik Språngceb44952020-09-22 09:36:35257 : trials_(std::move(trials)),
258 voice_engine_(std::move(audio_engine)),
Sebastian Janssonfa0aa392018-11-16 08:54:32259 video_engine_(std::move(video_engine)) {}
260
Erik Språngceb44952020-09-22 09:36:35261CompositeMediaEngine::CompositeMediaEngine(
262 std::unique_ptr<VoiceEngineInterface> audio_engine,
263 std::unique_ptr<VideoEngineInterface> video_engine)
264 : CompositeMediaEngine(nullptr,
265 std::move(audio_engine),
266 std::move(video_engine)) {}
267
Sebastian Janssonfa0aa392018-11-16 08:54:32268CompositeMediaEngine::~CompositeMediaEngine() = default;
269
270bool CompositeMediaEngine::Init() {
271 voice().Init();
272 return true;
273}
274
Sebastian Janssonfa0aa392018-11-16 08:54:32275VoiceEngineInterface& CompositeMediaEngine::voice() {
276 return *voice_engine_.get();
277}
278
279VideoEngineInterface& CompositeMediaEngine::video() {
280 return *video_engine_.get();
281}
282
283const VoiceEngineInterface& CompositeMediaEngine::voice() const {
284 return *voice_engine_.get();
285}
286
287const VideoEngineInterface& CompositeMediaEngine::video() const {
288 return *video_engine_.get();
289}
290
Nico Weber22f99252019-02-20 15:13:16291} // namespace cricket