RTCError CheckScalabilityModeValues(const RtpParameters& rtp_parameters,
std::span<const Codec> send_codecs,
std::optional<Codec> send_codec) {
if (send_codecs.empty()) { // This is an audio sender or an extra check in the stack where the codec // list is not available and we can't check the scalability_mode values. return RTCError::OK();
}
for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
if (rtp_parameters.encodings[i].codec) { bool codecFound = false;
for (const Codec& codec : send_codecs) {
if (IsSameRtpCodecIgnoringLevel(codec,
*rtp_parameters.encodings[i].codec) &&
SupportsMode(codec, rtp_parameters.encodings[i].scalability_mode)) {
codecFound = true;
send_codec = codec; break;
}
}
if (!codecFound) { return LOG_ERROR(RTCError(RTCErrorType::INVALID_MODIFICATION)
<< "Attempted to use an unsupported codec for layer "
<< i);
}
}
if (rtp_parameters.encodings[i].scalability_mode) {
if (!send_codec) { bool scalabilityModeFound = false;
for (const Codec& codec : send_codecs) {
for (constauto& scalability_mode : codec.scalability_modes) {
if (ScalabilityModeToString(scalability_mode) ==
*rtp_parameters.encodings[i].scalability_mode) {
scalabilityModeFound = true; break;
}
}
if (scalabilityModeFound) break;
}
if (!scalabilityModeFound) { return LOG_ERROR(
RTCError(RTCErrorType::INVALID_MODIFICATION)
<< "Attempted to set RtpParameters scalabilityMode " "to an unsupported value for the current codecs.");
}
} else { bool scalabilityModeFound = false;
for (constauto& scalability_mode : send_codec->scalability_modes) {
if (ScalabilityModeToString(scalability_mode) ==
*rtp_parameters.encodings[i].scalability_mode) {
scalabilityModeFound = true; break;
}
}
if (!scalabilityModeFound) { return LOG_ERROR(
RTCError(RTCErrorType::INVALID_MODIFICATION)
<< "Attempted to set RtpParameters scalabilityMode " "to an unsupported value for the current codecs.");
}
}
}
}
return RTCError::OK();
}
RTCError CheckRtpParametersValues(const RtpParameters& rtp_parameters,
std::span<const Codec> send_codecs,
std::optional<Codec> send_codec, const FieldTrialsView& field_trials) { bool has_scale_resolution_down_to = false;
for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
if (rtp_parameters.encodings[i].bitrate_priority <= 0) { return LOG_ERROR(RTCError(RTCErrorType::INVALID_RANGE)
<< "Attempted to set RtpParameters bitrate_priority to " "an invalid number. bitrate_priority must be > 0.");
}
if (rtp_parameters.encodings[i].scale_resolution_down_by &&
*rtp_parameters.encodings[i].scale_resolution_down_by < 1.0) { return LOG_ERROR(
RTCError(RTCErrorType::INVALID_RANGE)
<< "Attempted to set RtpParameters scale_resolution_down_by to an " "invalid value. scale_resolution_down_by must be >= 1.0");
}
if (rtp_parameters.encodings[i].max_framerate &&
*rtp_parameters.encodings[i].max_framerate < 0.0) { return LOG_ERROR(RTCError(RTCErrorType::INVALID_RANGE)
<< "Attempted to set RtpParameters max_framerate to an " "invalid value. max_framerate must be >= 0.0");
}
if (rtp_parameters.encodings[i].min_bitrate_bps &&
rtp_parameters.encodings[i].max_bitrate_bps) {
if (*rtp_parameters.encodings[i].max_bitrate_bps <
*rtp_parameters.encodings[i].min_bitrate_bps) { return LOG_ERROR(RTCError(RTCErrorType::INVALID_RANGE)
<< "Attempted to set RtpParameters min bitrate " "larger than max bitrate.");
}
}
if (rtp_parameters.encodings[i].num_temporal_layers) {
if (*rtp_parameters.encodings[i].num_temporal_layers < 1 ||
SafeGt(*rtp_parameters.encodings[i].num_temporal_layers,
kMaxTemporalStreams)) { return LOG_ERROR(RTCError(RTCErrorType::INVALID_RANGE)
<< "Attempted to set RtpParameters " "num_temporal_layers to an invalid number.");
}
}
if (rtp_parameters.encodings[i].scale_resolution_down_to.has_value()) {
has_scale_resolution_down_to = true;
if (rtp_parameters.encodings[i].scale_resolution_down_to->width <= 0 ||
rtp_parameters.encodings[i].scale_resolution_down_to->height <= 0) { return LOG_ERROR(RTCError(RTCErrorType::INVALID_MODIFICATION)
<< "The resolution dimensions must be positive.");
}
}
if (!field_trials.IsEnabled("WebRTC-MixedCodecSimulcast")) {
if (i > 0 && rtp_parameters.encodings[i - 1].codec !=
rtp_parameters.encodings[i].codec) { return LOG_ERROR(RTCError(RTCErrorType::UNSUPPORTED_OPERATION)
<< "Attempted to use different codec values for " "different encodings.");
}
}
if (rtp_parameters.encodings[i].csrcs.has_value() &&
rtp_parameters.encodings[i].csrcs.value().size() > kRtpCsrcSize) { return LOG_ERROR(
RTCError(RTCErrorType::INVALID_RANGE)
<< "Attempted to set more than the maximum allowed number of CSRCs.");
}
if (i > 0 && rtp_parameters.encodings[i - 1].csrcs !=
rtp_parameters.encodings[i].csrcs) { return LOG_ERROR(RTCError(RTCErrorType::INVALID_MODIFICATION)
<< "Attempted to set different CSRCs for different " "encodings.");
}
}
if (has_scale_resolution_down_to &&
absl::c_any_of(rtp_parameters.encodings,
[](const RtpEncodingParameters& encoding) { return encoding.active &&
!encoding.scale_resolution_down_to.has_value();
})) { return LOG_ERROR(RTCError(RTCErrorType::INVALID_MODIFICATION)
<< "If a resolution is specified on any encoding then " "it must be specified on all encodings.");
}
// In a mixed codec scenario, we only support scalability modes without // spatial layers.
if (rtp_parameters.IsMixedCodec()) {
for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) { auto scalability_mode = rtp_parameters.encodings[i].scalability_mode;
if (!scalability_mode) { continue;
} auto num_spatial_layers =
ScalabilityModeStringToNumSpatialLayers(*scalability_mode);
if (num_spatial_layers && *num_spatial_layers > 1) { return LOG_ERROR(
RTCError(RTCErrorType::UNSUPPORTED_OPERATION)
<< "Attempted to use a scalabilityMode with spatial layers in " "a mixed codec scenario.");
}
}
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.1Bemerkung:
(vorverarbeitet am 2026-08-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.