webrtc_media_engine.cc (6850B)
1 /* 2 * Copyright (c) 2014 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/engine/webrtc_media_engine.h" 12 13 #include <algorithm> 14 #include <map> 15 #include <string> 16 #include <vector> 17 18 #include "absl/algorithm/container.h" 19 #include "absl/strings/string_view.h" 20 #include "api/array_view.h" 21 #include "api/field_trials_view.h" 22 #include "api/rtp_parameters.h" 23 #include "api/transport/bitrate_settings.h" 24 #include "media/base/codec.h" 25 #include "media/base/media_constants.h" 26 #include "rtc_base/checks.h" 27 #include "rtc_base/logging.h" 28 29 namespace webrtc { 30 namespace { 31 // Remove mutually exclusive extensions with lower priority. 32 void DiscardRedundantExtensions( 33 std::vector<RtpExtension>* extensions, 34 ArrayView<const char* const> extensions_decreasing_prio) { 35 RTC_DCHECK(extensions); 36 bool found = false; 37 for (const char* uri : extensions_decreasing_prio) { 38 auto it = absl::c_find_if( 39 *extensions, [uri](const RtpExtension& rhs) { return rhs.uri == uri; }); 40 if (it != extensions->end()) { 41 if (found) { 42 extensions->erase(it); 43 } 44 found = true; 45 } 46 } 47 } 48 } // namespace 49 50 bool ValidateRtpExtensions(ArrayView<const RtpExtension> extensions, 51 ArrayView<const RtpExtension> old_extensions) { 52 bool id_used[1 + RtpExtension::kMaxId] = {false}; 53 for (const auto& extension : extensions) { 54 if (extension.id < RtpExtension::kMinId || 55 extension.id > RtpExtension::kMaxId) { 56 RTC_LOG(LS_ERROR) << "Bad RTP extension ID: " << extension.ToString(); 57 return false; 58 } 59 if (id_used[extension.id]) { 60 RTC_LOG(LS_ERROR) << "Duplicate RTP extension ID: " 61 << extension.ToString(); 62 return false; 63 } 64 id_used[extension.id] = true; 65 } 66 // Validate the extension list against the already negotiated extensions. 67 // Re-registering is OK, re-mapping (either same URL at new ID or same 68 // ID used with new URL) is an illegal remap. 69 70 // This is required in order to avoid a crash when registering an 71 // extension. A better structure would use the registered extensions 72 // in the RTPSender. This requires spinning through: 73 // 74 // WebRtcVoiceMediaChannel::::WebRtcAudioSendStream::stream_ (pointer) 75 // AudioSendStream::rtp_rtcp_module_ (pointer) 76 // ModuleRtpRtcpImpl2::rtp_sender_ (pointer) 77 // RtpSenderContext::packet_generator (struct member) 78 // RTPSender::rtp_header_extension_map_ (class member) 79 // 80 // Getting at this seems like a hard slog. 81 if (!old_extensions.empty()) { 82 absl::string_view urimap[1 + RtpExtension::kMaxId]; 83 std::map<absl::string_view, int> idmap; 84 for (const auto& old_extension : old_extensions) { 85 urimap[old_extension.id] = old_extension.uri; 86 idmap[old_extension.uri] = old_extension.id; 87 } 88 for (const auto& extension : extensions) { 89 if (!urimap[extension.id].empty() && 90 urimap[extension.id] != extension.uri) { 91 RTC_LOG(LS_ERROR) << "Extension negotiation failure: " << extension.id 92 << " was mapped to " << urimap[extension.id] 93 << " but is proposed changed to " << extension.uri; 94 return false; 95 } 96 const auto& it = idmap.find(extension.uri); 97 if (it != idmap.end() && it->second != extension.id) { 98 RTC_LOG(LS_ERROR) << "Extension negotation failure: " << extension.uri 99 << " was identified by " << it->second 100 << " but is proposed changed to " << extension.id; 101 return false; 102 } 103 } 104 } 105 return true; 106 } 107 108 std::vector<RtpExtension> FilterRtpExtensions( 109 const std::vector<RtpExtension>& extensions, 110 bool (*supported)(absl::string_view), 111 bool filter_redundant_extensions, 112 const FieldTrialsView& trials) { 113 // Don't check against old parameters; this should have been done earlier. 114 RTC_DCHECK(ValidateRtpExtensions(extensions, {})); 115 RTC_DCHECK(supported); 116 std::vector<RtpExtension> result; 117 118 // Ignore any extensions that we don't recognize. 119 for (const auto& extension : extensions) { 120 if (supported(extension.uri)) { 121 result.push_back(extension); 122 } else { 123 RTC_LOG(LS_WARNING) << "Unsupported RTP extension: " 124 << extension.ToString(); 125 } 126 } 127 128 // Sort by name, ascending (prioritise encryption), so that we don't reset 129 // extensions if they were specified in a different order (also allows us 130 // to use std::unique below). 131 absl::c_sort(result, [](const RtpExtension& rhs, const RtpExtension& lhs) { 132 return rhs.encrypt == lhs.encrypt ? rhs.uri < lhs.uri 133 : rhs.encrypt > lhs.encrypt; 134 }); 135 136 // Remove unnecessary extensions (used on send side). 137 if (filter_redundant_extensions) { 138 auto it = 139 std::unique(result.begin(), result.end(), 140 [](const RtpExtension& rhs, const RtpExtension& lhs) { 141 return rhs.uri == lhs.uri && rhs.encrypt == lhs.encrypt; 142 }); 143 result.erase(it, result.end()); 144 145 // Keep just the highest priority extension of any in the following lists. 146 if (trials.IsEnabled("WebRTC-FilterAbsSendTimeExtension")) { 147 static const char* const kBweExtensionPriorities[] = { 148 RtpExtension::kTransportSequenceNumberUri, 149 RtpExtension::kAbsSendTimeUri, RtpExtension::kTimestampOffsetUri}; 150 DiscardRedundantExtensions(&result, kBweExtensionPriorities); 151 } else { 152 static const char* const kBweExtensionPriorities[] = { 153 RtpExtension::kAbsSendTimeUri, RtpExtension::kTimestampOffsetUri}; 154 DiscardRedundantExtensions(&result, kBweExtensionPriorities); 155 } 156 } 157 return result; 158 } 159 160 BitrateConstraints GetBitrateConfigForCodec(const Codec& codec) { 161 BitrateConstraints config; 162 int bitrate_kbps = 0; 163 if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) && 164 bitrate_kbps > 0) { 165 config.min_bitrate_bps = bitrate_kbps * 1000; 166 } else { 167 config.min_bitrate_bps = 0; 168 } 169 if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) && 170 bitrate_kbps > 0) { 171 config.start_bitrate_bps = bitrate_kbps * 1000; 172 } else { 173 // Do not reconfigure start bitrate unless it's specified and positive. 174 config.start_bitrate_bps = -1; 175 } 176 if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) && 177 bitrate_kbps > 0) { 178 config.max_bitrate_bps = bitrate_kbps * 1000; 179 } else { 180 config.max_bitrate_bps = -1; 181 } 182 return config; 183 } 184 } // namespace webrtc