| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2017 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 | */ |
| Steve Anton | 10542f2 | 2019-01-11 17:11:00 | [diff] [blame] | 10 | #include "api/rtp_parameters.h" |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 11 | |
| 12 | #include <algorithm> |
| Dor Hen | aefed55 | 2024-06-18 13:20:35 | [diff] [blame] | 13 | #include <cstdint> |
| Shigemasa Watanabe | 63c20e9 | 2025-10-18 10:18:53 | [diff] [blame] | 14 | #include <optional> |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 15 | #include <string> |
| Tomas Gunnarsson | c69453d | 2022-01-06 12:36:04 | [diff] [blame] | 16 | #include <tuple> |
| Dor Hen | aefed55 | 2024-06-18 13:20:35 | [diff] [blame] | 17 | #include <vector> |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 18 | |
| Tommi | 932f274 | 2025-10-10 14:04:32 | [diff] [blame] | 19 | #include "absl/strings/ascii.h" |
| Dor Hen | aefed55 | 2024-06-18 13:20:35 | [diff] [blame] | 20 | #include "absl/strings/string_view.h" |
| Yves Gerey | 988cc08 | 2018-10-23 10:03:01 | [diff] [blame] | 21 | #include "api/array_view.h" |
| Tommi | 932f274 | 2025-10-10 14:04:32 | [diff] [blame] | 22 | #include "api/rtc_error.h" |
| Dor Hen | aefed55 | 2024-06-18 13:20:35 | [diff] [blame] | 23 | #include "api/rtp_transceiver_direction.h" |
| Philipp Hancke | b9405c4 | 2023-12-07 17:00:47 | [diff] [blame] | 24 | #include "media/base/media_constants.h" |
| Dor Hen | aefed55 | 2024-06-18 13:20:35 | [diff] [blame] | 25 | #include "rtc_base/checks.h" |
| Tommi | 932f274 | 2025-10-10 14:04:32 | [diff] [blame] | 26 | #include "rtc_base/logging.h" |
| 27 | #include "rtc_base/string_encode.h" |
| Jonas Olsson | 866d6dc | 2018-05-14 15:30:22 | [diff] [blame] | 28 | #include "rtc_base/strings/string_builder.h" |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 29 | |
| 30 | namespace webrtc { |
| Tommi | 932f274 | 2025-10-10 14:04:32 | [diff] [blame] | 31 | namespace { |
| 32 | constexpr char kSdpDelimiterSemicolon[] = ";"; |
| 33 | constexpr char kSdpDelimiterEqualChar = '='; |
| 34 | constexpr char kSdpDelimiterEqual[] = "="; |
| 35 | constexpr char kSdpDelimiterSemicolonChar = ';'; |
| 36 | |
| 37 | void ParseFmtpParam(absl::string_view line, |
| 38 | std::string* parameter, |
| 39 | std::string* value) { |
| 40 | if (!tokenize_first(line, kSdpDelimiterEqualChar, parameter, value)) { |
| 41 | // Support for non-key-value lines like RFC 2198 or RFC 4733. |
| 42 | *parameter = ""; |
| 43 | *value = std::string(line); |
| 44 | } |
| 45 | // a=fmtp:<payload_type> <param1>=<value1>; <param2>=<value2>; ... |
| 46 | } |
| 47 | |
| 48 | bool IsFmtpParam(absl::string_view name) { |
| 49 | // RFC 4855, section 3 specifies the mapping of media format parameters to SDP |
| 50 | // parameters. Only ptime, maxptime, channels and rate are placed outside of |
| 51 | // the fmtp line. In WebRTC, channels and rate are already handled separately |
| 52 | // and thus not included in the CodecParameterMap. |
| 53 | return name != kCodecParamPTime && name != kCodecParamMaxPTime; |
| 54 | } |
| 55 | |
| 56 | void WriteFmtpParameter(absl::string_view parameter_name, |
| 57 | absl::string_view parameter_value, |
| 58 | StringBuilder& os) { |
| 59 | if (parameter_name.empty()) { |
| 60 | // RFC 2198 and RFC 4733 don't use key-value pairs. |
| 61 | os << parameter_value; |
| 62 | } else { |
| 63 | // fmtp parameters: `parameter_name`=`parameter_value` |
| 64 | os << parameter_name << kSdpDelimiterEqual << parameter_value; |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | } // namespace |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 69 | |
| Henrik Boström | f0eef12 | 2020-05-28 14:22:42 | [diff] [blame] | 70 | const char* DegradationPreferenceToString( |
| 71 | DegradationPreference degradation_preference) { |
| 72 | switch (degradation_preference) { |
| Sergey Silkin | 9559309 | 2025-10-10 11:14:00 | [diff] [blame] | 73 | case DegradationPreference::MAINTAIN_FRAMERATE_AND_RESOLUTION: |
| 74 | return "maintain-framerate-and-resolution"; |
| Henrik Boström | f0eef12 | 2020-05-28 14:22:42 | [diff] [blame] | 75 | case DegradationPreference::MAINTAIN_FRAMERATE: |
| 76 | return "maintain-framerate"; |
| 77 | case DegradationPreference::MAINTAIN_RESOLUTION: |
| 78 | return "maintain-resolution"; |
| 79 | case DegradationPreference::BALANCED: |
| 80 | return "balanced"; |
| 81 | } |
| Karl Wiberg | c95b939 | 2020-11-07 23:49:37 | [diff] [blame] | 82 | RTC_CHECK_NOTREACHED(); |
| Henrik Boström | f0eef12 | 2020-05-28 14:22:42 | [diff] [blame] | 83 | } |
| 84 | |
| Seth Hampson | f32795e | 2017-12-19 19:37:41 | [diff] [blame] | 85 | const double kDefaultBitratePriority = 1.0; |
| 86 | |
| Tommi | 932f274 | 2025-10-10 14:04:32 | [diff] [blame] | 87 | bool WriteFmtpParameters(const CodecParameterMap& parameters, |
| 88 | StringBuilder& os) { |
| 89 | bool empty = true; |
| 90 | const char* delimiter = ""; // No delimiter before first parameter. |
| 91 | for (const auto& entry : parameters) { |
| 92 | const std::string& key = entry.first; |
| 93 | const std::string& value = entry.second; |
| 94 | |
| 95 | if (IsFmtpParam(key)) { |
| 96 | os << delimiter; |
| 97 | // A semicolon before each subsequent parameter. |
| 98 | delimiter = kSdpDelimiterSemicolon; |
| 99 | WriteFmtpParameter(key, value, os); |
| 100 | empty = false; |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | return !empty; |
| 105 | } |
| 106 | |
| 107 | RTCError ParseFmtpParameterSet(absl::string_view line_params, |
| 108 | CodecParameterMap& codec_params) { |
| 109 | // Parse out format specific parameters. |
| 110 | for (absl::string_view param : |
| 111 | split(line_params, kSdpDelimiterSemicolonChar)) { |
| 112 | std::string name; |
| 113 | std::string value; |
| 114 | ParseFmtpParam(absl::StripAsciiWhitespace(param), &name, &value); |
| 115 | if (codec_params.find(name) != codec_params.end()) { |
| 116 | RTC_LOG(LS_INFO) << "Overwriting duplicate fmtp parameter with key \"" |
| 117 | << name << "\"."; |
| 118 | } |
| 119 | codec_params[name] = value; |
| 120 | } |
| 121 | return RTCError::OK(); |
| 122 | } |
| 123 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 124 | RtcpFeedback::RtcpFeedback() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 125 | RtcpFeedback::RtcpFeedback(RtcpFeedbackType type) : type(type) {} |
| 126 | RtcpFeedback::RtcpFeedback(RtcpFeedbackType type, |
| 127 | RtcpFeedbackMessageType message_type) |
| 128 | : type(type), message_type(message_type) {} |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 129 | RtcpFeedback::RtcpFeedback(const RtcpFeedback& rhs) = default; |
| 130 | RtcpFeedback::~RtcpFeedback() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 131 | |
| Florent Castelli | 0a4a984 | 2023-04-03 17:25:29 | [diff] [blame] | 132 | RtpCodec::RtpCodec() = default; |
| 133 | RtpCodec::RtpCodec(const RtpCodec&) = default; |
| 134 | RtpCodec::~RtpCodec() = default; |
| Philipp Hancke | b9405c4 | 2023-12-07 17:00:47 | [diff] [blame] | 135 | bool RtpCodec::IsResiliencyCodec() const { |
| Evan Shrubsole | 945e517 | 2025-04-08 14:11:45 | [diff] [blame] | 136 | return name == kRtxCodecName || name == kRedCodecName || |
| 137 | name == kUlpfecCodecName || name == kFlexfecCodecName; |
| Philipp Hancke | b9405c4 | 2023-12-07 17:00:47 | [diff] [blame] | 138 | } |
| 139 | bool RtpCodec::IsMediaCodec() const { |
| Evan Shrubsole | 945e517 | 2025-04-08 14:11:45 | [diff] [blame] | 140 | return !IsResiliencyCodec() && name != kComfortNoiseCodecName; |
| Philipp Hancke | b9405c4 | 2023-12-07 17:00:47 | [diff] [blame] | 141 | } |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 142 | RtpCodecCapability::RtpCodecCapability() = default; |
| 143 | RtpCodecCapability::~RtpCodecCapability() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 144 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 145 | RtpHeaderExtensionCapability::RtpHeaderExtensionCapability() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 146 | RtpHeaderExtensionCapability::RtpHeaderExtensionCapability( |
| Danil Chapovalov | 2b4ec9e | 2020-03-25 16:23:37 | [diff] [blame] | 147 | absl::string_view uri) |
| 148 | : uri(uri) {} |
| 149 | RtpHeaderExtensionCapability::RtpHeaderExtensionCapability( |
| 150 | absl::string_view uri, |
| 151 | int preferred_id) |
| 152 | : uri(uri), preferred_id(preferred_id) {} |
| 153 | RtpHeaderExtensionCapability::RtpHeaderExtensionCapability( |
| 154 | absl::string_view uri, |
| Markus Handell | 0357b3e | 2020-03-16 12:40:51 | [diff] [blame] | 155 | int preferred_id, |
| 156 | RtpTransceiverDirection direction) |
| Danil Chapovalov | 2b4ec9e | 2020-03-25 16:23:37 | [diff] [blame] | 157 | : uri(uri), preferred_id(preferred_id), direction(direction) {} |
| Emil Vardar | f5a547a | 2024-09-26 11:06:07 | [diff] [blame] | 158 | RtpHeaderExtensionCapability::RtpHeaderExtensionCapability( |
| 159 | absl::string_view uri, |
| 160 | int preferred_id, |
| 161 | bool preferred_encrypt, |
| 162 | RtpTransceiverDirection direction) |
| 163 | : uri(uri), |
| 164 | preferred_id(preferred_id), |
| 165 | preferred_encrypt(preferred_encrypt), |
| 166 | direction(direction) {} |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 167 | RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 168 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 169 | RtpExtension::RtpExtension() = default; |
| Danil Chapovalov | 2b4ec9e | 2020-03-25 16:23:37 | [diff] [blame] | 170 | RtpExtension::RtpExtension(absl::string_view uri, int id) : uri(uri), id(id) {} |
| 171 | RtpExtension::RtpExtension(absl::string_view uri, int id, bool encrypt) |
| 172 | : uri(uri), id(id), encrypt(encrypt) {} |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 173 | RtpExtension::~RtpExtension() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 174 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 175 | RtpFecParameters::RtpFecParameters() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 176 | RtpFecParameters::RtpFecParameters(FecMechanism mechanism) |
| 177 | : mechanism(mechanism) {} |
| 178 | RtpFecParameters::RtpFecParameters(FecMechanism mechanism, uint32_t ssrc) |
| 179 | : ssrc(ssrc), mechanism(mechanism) {} |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 180 | RtpFecParameters::RtpFecParameters(const RtpFecParameters& rhs) = default; |
| 181 | RtpFecParameters::~RtpFecParameters() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 182 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 183 | RtpRtxParameters::RtpRtxParameters() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 184 | RtpRtxParameters::RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {} |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 185 | RtpRtxParameters::RtpRtxParameters(const RtpRtxParameters& rhs) = default; |
| 186 | RtpRtxParameters::~RtpRtxParameters() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 187 | |
| Henrik Boström | 440ef02 | 2024-10-24 08:40:58 | [diff] [blame] | 188 | RtpEncodingParameters::RtpEncodingParameters() = default; |
| 189 | RtpEncodingParameters::RtpEncodingParameters(const RtpEncodingParameters& rhs) = |
| 190 | default; |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 191 | RtpEncodingParameters::~RtpEncodingParameters() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 192 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 193 | RtpCodecParameters::RtpCodecParameters() = default; |
| 194 | RtpCodecParameters::RtpCodecParameters(const RtpCodecParameters& rhs) = default; |
| 195 | RtpCodecParameters::~RtpCodecParameters() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 196 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 197 | RtpCapabilities::RtpCapabilities() = default; |
| 198 | RtpCapabilities::~RtpCapabilities() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 199 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 200 | RtcpParameters::RtcpParameters() = default; |
| 201 | RtcpParameters::RtcpParameters(const RtcpParameters& rhs) = default; |
| 202 | RtcpParameters::~RtcpParameters() = default; |
| Florent Castelli | dacec71 | 2018-05-24 14:24:21 | [diff] [blame] | 203 | |
| Mirko Bonadei | 2ffed6d | 2018-07-20 09:09:32 | [diff] [blame] | 204 | RtpParameters::RtpParameters() = default; |
| 205 | RtpParameters::RtpParameters(const RtpParameters& rhs) = default; |
| 206 | RtpParameters::~RtpParameters() = default; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 207 | |
| 208 | std::string RtpExtension::ToString() const { |
| Jonas Olsson | 866d6dc | 2018-05-14 15:30:22 | [diff] [blame] | 209 | char buf[256]; |
| Evan Shrubsole | 0ebd67f | 2025-02-19 10:06:32 | [diff] [blame] | 210 | SimpleStringBuilder sb(buf); |
| Jonas Olsson | 866d6dc | 2018-05-14 15:30:22 | [diff] [blame] | 211 | sb << "{uri: " << uri; |
| 212 | sb << ", id: " << id; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 213 | if (encrypt) { |
| Jonas Olsson | 866d6dc | 2018-05-14 15:30:22 | [diff] [blame] | 214 | sb << ", encrypt"; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 215 | } |
| Jonas Olsson | 866d6dc | 2018-05-14 15:30:22 | [diff] [blame] | 216 | sb << '}'; |
| 217 | return sb.str(); |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 218 | } |
| 219 | |
| Markus Handell | dfeb0df | 2020-03-16 21:20:47 | [diff] [blame] | 220 | bool RtpExtension::IsSupportedForAudio(absl::string_view uri) { |
| Evan Shrubsole | 2f5c266 | 2025-05-12 07:43:09 | [diff] [blame] | 221 | return uri == RtpExtension::kAudioLevelUri || |
| 222 | uri == RtpExtension::kAbsSendTimeUri || |
| 223 | uri == RtpExtension::kAbsoluteCaptureTimeUri || |
| 224 | uri == RtpExtension::kTransportSequenceNumberUri || |
| 225 | uri == RtpExtension::kTransportSequenceNumberV2Uri || |
| 226 | uri == RtpExtension::kMidUri || uri == RtpExtension::kRidUri || |
| 227 | uri == RtpExtension::kRepairedRidUri; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 228 | } |
| 229 | |
| Markus Handell | dfeb0df | 2020-03-16 21:20:47 | [diff] [blame] | 230 | bool RtpExtension::IsSupportedForVideo(absl::string_view uri) { |
| Evan Shrubsole | 2f5c266 | 2025-05-12 07:43:09 | [diff] [blame] | 231 | return uri == RtpExtension::kTimestampOffsetUri || |
| 232 | uri == RtpExtension::kAbsSendTimeUri || |
| 233 | uri == RtpExtension::kAbsoluteCaptureTimeUri || |
| 234 | uri == RtpExtension::kVideoRotationUri || |
| 235 | uri == RtpExtension::kTransportSequenceNumberUri || |
| 236 | uri == RtpExtension::kTransportSequenceNumberV2Uri || |
| 237 | uri == RtpExtension::kPlayoutDelayUri || |
| 238 | uri == RtpExtension::kVideoContentTypeUri || |
| 239 | uri == RtpExtension::kVideoTimingUri || uri == RtpExtension::kMidUri || |
| 240 | uri == RtpExtension::kGenericFrameDescriptorUri00 || |
| 241 | uri == RtpExtension::kDependencyDescriptorUri || |
| 242 | uri == RtpExtension::kColorSpaceUri || uri == RtpExtension::kRidUri || |
| 243 | uri == RtpExtension::kRepairedRidUri || |
| 244 | uri == RtpExtension::kVideoLayersAllocationUri || |
| 245 | uri == RtpExtension::kVideoFrameTrackingIdUri || |
| 246 | uri == RtpExtension::kCorruptionDetectionUri; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 247 | } |
| 248 | |
| Markus Handell | dfeb0df | 2020-03-16 21:20:47 | [diff] [blame] | 249 | bool RtpExtension::IsEncryptionSupported(absl::string_view uri) { |
| Lennart Grahl | 0d0ed76 | 2021-05-17 14:06:37 | [diff] [blame] | 250 | return |
| 251 | #if defined(ENABLE_EXTERNAL_AUTH) |
| 252 | // TODO(jbauch): Figure out a way to always allow "kAbsSendTimeUri" |
| 253 | // here and filter out later if external auth is really used in |
| 254 | // srtpfilter. External auth is used by Chromium and replaces the |
| 255 | // extension header value of "kAbsSendTimeUri", so it must not be |
| 256 | // encrypted (which can't be done by Chromium). |
| Harald Alvestrand | 3d12066 | 2025-06-11 07:34:39 | [diff] [blame] | 257 | uri != RtpExtension::kAbsSendTimeUri && |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 258 | #endif |
| Evan Shrubsole | 2f5c266 | 2025-05-12 07:43:09 | [diff] [blame] | 259 | uri != RtpExtension::kEncryptHeaderExtensionsUri; |
| Lennart Grahl | 0d0ed76 | 2021-05-17 14:06:37 | [diff] [blame] | 260 | } |
| 261 | |
| 262 | // Returns whether a header extension with the given URI exists. |
| 263 | // Note: This does not differentiate between encrypted and non-encrypted |
| 264 | // extensions, so use with care! |
| 265 | static bool HeaderExtensionWithUriExists( |
| 266 | const std::vector<RtpExtension>& extensions, |
| 267 | absl::string_view uri) { |
| 268 | for (const auto& extension : extensions) { |
| 269 | if (extension.uri == uri) { |
| 270 | return true; |
| 271 | } |
| 272 | } |
| 273 | return false; |
| 274 | } |
| 275 | |
| 276 | const RtpExtension* RtpExtension::FindHeaderExtensionByUri( |
| 277 | const std::vector<RtpExtension>& extensions, |
| 278 | absl::string_view uri, |
| 279 | Filter filter) { |
| Evan Shrubsole | 2f5c266 | 2025-05-12 07:43:09 | [diff] [blame] | 280 | const RtpExtension* fallback_extension = nullptr; |
| Lennart Grahl | 0d0ed76 | 2021-05-17 14:06:37 | [diff] [blame] | 281 | for (const auto& extension : extensions) { |
| 282 | if (extension.uri != uri) { |
| 283 | continue; |
| 284 | } |
| 285 | |
| 286 | switch (filter) { |
| 287 | case kDiscardEncryptedExtension: |
| 288 | // We only accept an unencrypted extension. |
| 289 | if (!extension.encrypt) { |
| 290 | return &extension; |
| 291 | } |
| 292 | break; |
| 293 | |
| 294 | case kPreferEncryptedExtension: |
| 295 | // We prefer an encrypted extension but we can fall back to an |
| 296 | // unencrypted extension. |
| 297 | if (extension.encrypt) { |
| 298 | return &extension; |
| 299 | } else { |
| 300 | fallback_extension = &extension; |
| 301 | } |
| 302 | break; |
| 303 | |
| 304 | case kRequireEncryptedExtension: |
| 305 | // We only accept an encrypted extension. |
| 306 | if (extension.encrypt) { |
| 307 | return &extension; |
| 308 | } |
| 309 | break; |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | // Returning fallback extension (if any) |
| 314 | return fallback_extension; |
| Lennart Grahl | a743303 | 2021-04-09 20:05:06 | [diff] [blame] | 315 | } |
| 316 | |
| Lennart Grahl | 0d0ed76 | 2021-05-17 14:06:37 | [diff] [blame] | 317 | const RtpExtension* RtpExtension::FindHeaderExtensionByUriAndEncryption( |
| 318 | const std::vector<RtpExtension>& extensions, |
| 319 | absl::string_view uri, |
| 320 | bool encrypt) { |
| Lennart Grahl | a743303 | 2021-04-09 20:05:06 | [diff] [blame] | 321 | for (const auto& extension : extensions) { |
| Lennart Grahl | 0d0ed76 | 2021-05-17 14:06:37 | [diff] [blame] | 322 | if (extension.uri == uri && extension.encrypt == encrypt) { |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 323 | return &extension; |
| 324 | } |
| 325 | } |
| 326 | return nullptr; |
| 327 | } |
| 328 | |
| Lennart Grahl | 0d0ed76 | 2021-05-17 14:06:37 | [diff] [blame] | 329 | const std::vector<RtpExtension> RtpExtension::DeduplicateHeaderExtensions( |
| 330 | const std::vector<RtpExtension>& extensions, |
| 331 | Filter filter) { |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 332 | std::vector<RtpExtension> filtered; |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 333 | |
| Lennart Grahl | 0d0ed76 | 2021-05-17 14:06:37 | [diff] [blame] | 334 | // If we do not discard encrypted extensions, add them first |
| 335 | if (filter != kDiscardEncryptedExtension) { |
| 336 | for (const auto& extension : extensions) { |
| 337 | if (!extension.encrypt) { |
| 338 | continue; |
| 339 | } |
| 340 | if (!HeaderExtensionWithUriExists(filtered, extension.uri)) { |
| 341 | filtered.push_back(extension); |
| 342 | } |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 343 | } |
| 344 | } |
| Lennart Grahl | 0d0ed76 | 2021-05-17 14:06:37 | [diff] [blame] | 345 | |
| 346 | // If we do not require encrypted extensions, add missing, non-encrypted |
| 347 | // extensions. |
| 348 | if (filter != kRequireEncryptedExtension) { |
| 349 | for (const auto& extension : extensions) { |
| 350 | if (extension.encrypt) { |
| 351 | continue; |
| 352 | } |
| 353 | if (!HeaderExtensionWithUriExists(filtered, extension.uri)) { |
| 354 | filtered.push_back(extension); |
| 355 | } |
| 356 | } |
| 357 | } |
| 358 | |
| Tomas Gunnarsson | c69453d | 2022-01-06 12:36:04 | [diff] [blame] | 359 | // Sort the returned vector to make comparisons of header extensions reliable. |
| 360 | // In order of priority, we sort by uri first, then encrypt and id last. |
| 361 | std::sort(filtered.begin(), filtered.end(), |
| 362 | [](const RtpExtension& a, const RtpExtension& b) { |
| 363 | return std::tie(a.uri, a.encrypt, a.id) < |
| 364 | std::tie(b.uri, b.encrypt, b.id); |
| 365 | }); |
| 366 | |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 367 | return filtered; |
| 368 | } |
| Shigemasa Watanabe | 63c20e9 | 2025-10-18 10:18:53 | [diff] [blame] | 369 | |
| 370 | bool RtpParameters::IsMixedCodec() const { |
| 371 | std::optional<std::optional<RtpCodec>> first_codec; |
| 372 | for (const RtpEncodingParameters& encoding : encodings) { |
| 373 | if (!encoding.active) { |
| 374 | continue; |
| 375 | } |
| 376 | if (!first_codec) { |
| 377 | first_codec = encoding.codec; |
| 378 | continue; |
| 379 | } |
| 380 | if (*first_codec != encoding.codec) { |
| 381 | return true; |
| 382 | } |
| 383 | } |
| 384 | return false; |
| 385 | } |
| 386 | |
| Stefan Holmer | 1acbd68 | 2017-09-01 13:29:28 | [diff] [blame] | 387 | } // namespace webrtc |