/* * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "media/base/media_engine.h" #include #include #include #include #include "absl/algorithm/container.h" #include "api/video/video_bitrate_allocation.h" #include "rtc_base/checks.h" #include "rtc_base/string_encode.h" namespace cricket { RtpCapabilities::RtpCapabilities() = default; RtpCapabilities::~RtpCapabilities() = default; webrtc::RtpParameters CreateRtpParametersWithOneEncoding() { webrtc::RtpParameters parameters; webrtc::RtpEncodingParameters encoding; parameters.encodings.push_back(encoding); return parameters; } webrtc::RtpParameters CreateRtpParametersWithEncodings(StreamParams sp) { std::vector primary_ssrcs; sp.GetPrimarySsrcs(&primary_ssrcs); size_t encoding_count = primary_ssrcs.size(); std::vector encodings(encoding_count); for (size_t i = 0; i < encodings.size(); ++i) { encodings[i].ssrc = primary_ssrcs[i]; } const std::vector& rids = sp.rids(); RTC_DCHECK(rids.size() == 0 || rids.size() == encoding_count); for (size_t i = 0; i < rids.size(); ++i) { encodings[i].rid = rids[i].rid; } webrtc::RtpParameters parameters; parameters.encodings = encodings; parameters.rtcp.cname = sp.cname; return parameters; } std::vector GetDefaultEnabledRtpHeaderExtensions( const RtpHeaderExtensionQueryInterface& query_interface) { std::vector extensions; for (const auto& entry : query_interface.GetRtpHeaderExtensions()) { if (entry.direction != webrtc::RtpTransceiverDirection::kStopped) extensions.emplace_back(entry.uri, *entry.preferred_id); } return extensions; } webrtc::RTCError CheckScalabilityModeValues( const webrtc::RtpParameters& rtp_parameters, rtc::ArrayView codecs) { using webrtc::RTCErrorType; if (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 webrtc::RTCError::OK(); } for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) { if (rtp_parameters.encodings[i].scalability_mode) { bool scalabilityModeFound = false; for (const cricket::VideoCodec& codec : codecs) { for (const auto& scalability_mode : codec.scalability_modes) { if (ScalabilityModeToString(scalability_mode) == *rtp_parameters.encodings[i].scalability_mode) { scalabilityModeFound = true; break; } } if (scalabilityModeFound) break; } if (!scalabilityModeFound) { LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION, "Attempted to set RtpParameters scalabilityMode " "to an unsupported value for the current codecs."); } } } return webrtc::RTCError::OK(); } webrtc::RTCError CheckRtpParametersValues( const webrtc::RtpParameters& rtp_parameters, rtc::ArrayView codecs) { using webrtc::RTCErrorType; for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) { if (rtp_parameters.encodings[i].bitrate_priority <= 0) { LOG_AND_RETURN_ERROR(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) { LOG_AND_RETURN_ERROR( 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) { LOG_AND_RETURN_ERROR(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) { LOG_AND_RETURN_ERROR(webrtc::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 || *rtp_parameters.encodings[i].num_temporal_layers > webrtc::kMaxTemporalStreams) { LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, "Attempted to set RtpParameters " "num_temporal_layers to an invalid number."); } } if (rtp_parameters.encodings[i].requested_resolution && rtp_parameters.encodings[i].scale_resolution_down_by) { LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, "Attempted to set scale_resolution_down_by and " "requested_resolution simultaniously."); } } return CheckScalabilityModeValues(rtp_parameters, codecs); } webrtc::RTCError CheckRtpParametersInvalidModificationAndValues( const webrtc::RtpParameters& old_rtp_parameters, const webrtc::RtpParameters& rtp_parameters) { return CheckRtpParametersInvalidModificationAndValues(old_rtp_parameters, rtp_parameters, {}); } webrtc::RTCError CheckRtpParametersInvalidModificationAndValues( const webrtc::RtpParameters& old_rtp_parameters, const webrtc::RtpParameters& rtp_parameters, rtc::ArrayView codecs) { using webrtc::RTCErrorType; if (rtp_parameters.encodings.size() != old_rtp_parameters.encodings.size()) { LOG_AND_RETURN_ERROR( RTCErrorType::INVALID_MODIFICATION, "Attempted to set RtpParameters with different encoding count"); } if (rtp_parameters.rtcp != old_rtp_parameters.rtcp) { LOG_AND_RETURN_ERROR( RTCErrorType::INVALID_MODIFICATION, "Attempted to set RtpParameters with modified RTCP parameters"); } if (rtp_parameters.header_extensions != old_rtp_parameters.header_extensions) { LOG_AND_RETURN_ERROR( RTCErrorType::INVALID_MODIFICATION, "Attempted to set RtpParameters with modified header extensions"); } if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings, [](const webrtc::RtpEncodingParameters& encoding1, const webrtc::RtpEncodingParameters& encoding2) { return encoding1.rid == encoding2.rid; })) { LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION, "Attempted to change RID values in the encodings."); } if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings, [](const webrtc::RtpEncodingParameters& encoding1, const webrtc::RtpEncodingParameters& encoding2) { return encoding1.ssrc == encoding2.ssrc; })) { LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION, "Attempted to set RtpParameters with modified SSRC"); } return CheckRtpParametersValues(rtp_parameters, codecs); } CompositeMediaEngine::CompositeMediaEngine( std::unique_ptr trials, std::unique_ptr audio_engine, std::unique_ptr video_engine) : trials_(std::move(trials)), voice_engine_(std::move(audio_engine)), video_engine_(std::move(video_engine)) {} CompositeMediaEngine::CompositeMediaEngine( std::unique_ptr audio_engine, std::unique_ptr video_engine) : CompositeMediaEngine(nullptr, std::move(audio_engine), std::move(video_engine)) {} CompositeMediaEngine::~CompositeMediaEngine() = default; bool CompositeMediaEngine::Init() { voice().Init(); return true; } VoiceEngineInterface& CompositeMediaEngine::voice() { return *voice_engine_.get(); } VideoEngineInterface& CompositeMediaEngine::video() { return *video_engine_.get(); } const VoiceEngineInterface& CompositeMediaEngine::voice() const { return *voice_engine_.get(); } const VideoEngineInterface& CompositeMediaEngine::video() const { return *video_engine_.get(); } } // namespace cricket