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 
CheckRtpParametersValues(const webrtc::RtpParameters & rtp_parameters)68 webrtc::RTCError CheckRtpParametersValues(
69     const webrtc::RtpParameters& rtp_parameters) {
70   using webrtc::RTCErrorType;
71 
72   for (size_t i = 0; i < rtp_parameters.encodings.size(); ++i) {
73     if (rtp_parameters.encodings[i].bitrate_priority <= 0) {
74       LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
75                            "Attempted to set RtpParameters bitrate_priority to "
76                            "an invalid number. bitrate_priority must be > 0.");
77     }
78     if (rtp_parameters.encodings[i].scale_resolution_down_by &&
79         *rtp_parameters.encodings[i].scale_resolution_down_by < 1.0) {
80       LOG_AND_RETURN_ERROR(
81           RTCErrorType::INVALID_RANGE,
82           "Attempted to set RtpParameters scale_resolution_down_by to an "
83           "invalid value. scale_resolution_down_by must be >= 1.0");
84     }
85     if (rtp_parameters.encodings[i].max_framerate &&
86         *rtp_parameters.encodings[i].max_framerate < 0.0) {
87       LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
88                            "Attempted to set RtpParameters max_framerate to an "
89                            "invalid value. max_framerate must be >= 0.0");
90     }
91     if (rtp_parameters.encodings[i].min_bitrate_bps &&
92         rtp_parameters.encodings[i].max_bitrate_bps) {
93       if (*rtp_parameters.encodings[i].max_bitrate_bps <
94           *rtp_parameters.encodings[i].min_bitrate_bps) {
95         LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::INVALID_RANGE,
96                              "Attempted to set RtpParameters min bitrate "
97                              "larger than max bitrate.");
98       }
99     }
100     if (rtp_parameters.encodings[i].num_temporal_layers) {
101       if (*rtp_parameters.encodings[i].num_temporal_layers < 1 ||
102           *rtp_parameters.encodings[i].num_temporal_layers >
103               webrtc::kMaxTemporalStreams) {
104         LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
105                              "Attempted to set RtpParameters "
106                              "num_temporal_layers to an invalid number.");
107       }
108     }
109     if (i > 0 && (rtp_parameters.encodings[i].num_temporal_layers !=
110                   rtp_parameters.encodings[i - 1].num_temporal_layers)) {
111       LOG_AND_RETURN_ERROR(
112           RTCErrorType::INVALID_MODIFICATION,
113           "Attempted to set RtpParameters num_temporal_layers "
114           "at encoding layer i: " +
115               rtc::ToString(i) +
116               " to a different value than other encoding layers.");
117     }
118   }
119 
120   return webrtc::RTCError::OK();
121 }
122 
CheckRtpParametersInvalidModificationAndValues(const webrtc::RtpParameters & old_rtp_parameters,const webrtc::RtpParameters & rtp_parameters)123 webrtc::RTCError CheckRtpParametersInvalidModificationAndValues(
124     const webrtc::RtpParameters& old_rtp_parameters,
125     const webrtc::RtpParameters& rtp_parameters) {
126   using webrtc::RTCErrorType;
127   if (rtp_parameters.encodings.size() != old_rtp_parameters.encodings.size()) {
128     LOG_AND_RETURN_ERROR(
129         RTCErrorType::INVALID_MODIFICATION,
130         "Attempted to set RtpParameters with different encoding count");
131   }
132   if (rtp_parameters.rtcp != old_rtp_parameters.rtcp) {
133     LOG_AND_RETURN_ERROR(
134         RTCErrorType::INVALID_MODIFICATION,
135         "Attempted to set RtpParameters with modified RTCP parameters");
136   }
137   if (rtp_parameters.header_extensions !=
138       old_rtp_parameters.header_extensions) {
139     LOG_AND_RETURN_ERROR(
140         RTCErrorType::INVALID_MODIFICATION,
141         "Attempted to set RtpParameters with modified header extensions");
142   }
143   if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
144                      [](const webrtc::RtpEncodingParameters& encoding1,
145                         const webrtc::RtpEncodingParameters& encoding2) {
146                        return encoding1.rid == encoding2.rid;
147                      })) {
148     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
149                          "Attempted to change RID values in the encodings.");
150   }
151   if (!absl::c_equal(old_rtp_parameters.encodings, rtp_parameters.encodings,
152                      [](const webrtc::RtpEncodingParameters& encoding1,
153                         const webrtc::RtpEncodingParameters& encoding2) {
154                        return encoding1.ssrc == encoding2.ssrc;
155                      })) {
156     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
157                          "Attempted to set RtpParameters with modified SSRC");
158   }
159 
160   return CheckRtpParametersValues(rtp_parameters);
161 }
162 
CompositeMediaEngine(std::unique_ptr<VoiceEngineInterface> voice_engine,std::unique_ptr<VideoEngineInterface> video_engine)163 CompositeMediaEngine::CompositeMediaEngine(
164     std::unique_ptr<VoiceEngineInterface> voice_engine,
165     std::unique_ptr<VideoEngineInterface> video_engine)
166     : voice_engine_(std::move(voice_engine)),
167       video_engine_(std::move(video_engine)) {}
168 
169 CompositeMediaEngine::~CompositeMediaEngine() = default;
170 
Init()171 bool CompositeMediaEngine::Init() {
172   voice().Init();
173   return true;
174 }
175 
voice()176 VoiceEngineInterface& CompositeMediaEngine::voice() {
177   return *voice_engine_.get();
178 }
179 
video()180 VideoEngineInterface& CompositeMediaEngine::video() {
181   return *video_engine_.get();
182 }
183 
voice() const184 const VoiceEngineInterface& CompositeMediaEngine::voice() const {
185   return *voice_engine_.get();
186 }
187 
video() const188 const VideoEngineInterface& CompositeMediaEngine::video() const {
189   return *video_engine_.get();
190 }
191 
192 }  // namespace cricket
193