xref: /aosp_15_r20/external/webrtc/api/rtp_parameters.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
11*d9f75844SAndroid Build Coastguard Worker 
12*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
13*d9f75844SAndroid Build Coastguard Worker #include <string>
14*d9f75844SAndroid Build Coastguard Worker #include <tuple>
15*d9f75844SAndroid Build Coastguard Worker #include <utility>
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker #include "api/array_view.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
21*d9f75844SAndroid Build Coastguard Worker 
DegradationPreferenceToString(DegradationPreference degradation_preference)22*d9f75844SAndroid Build Coastguard Worker const char* DegradationPreferenceToString(
23*d9f75844SAndroid Build Coastguard Worker     DegradationPreference degradation_preference) {
24*d9f75844SAndroid Build Coastguard Worker   switch (degradation_preference) {
25*d9f75844SAndroid Build Coastguard Worker     case DegradationPreference::DISABLED:
26*d9f75844SAndroid Build Coastguard Worker       return "disabled";
27*d9f75844SAndroid Build Coastguard Worker     case DegradationPreference::MAINTAIN_FRAMERATE:
28*d9f75844SAndroid Build Coastguard Worker       return "maintain-framerate";
29*d9f75844SAndroid Build Coastguard Worker     case DegradationPreference::MAINTAIN_RESOLUTION:
30*d9f75844SAndroid Build Coastguard Worker       return "maintain-resolution";
31*d9f75844SAndroid Build Coastguard Worker     case DegradationPreference::BALANCED:
32*d9f75844SAndroid Build Coastguard Worker       return "balanced";
33*d9f75844SAndroid Build Coastguard Worker   }
34*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK_NOTREACHED();
35*d9f75844SAndroid Build Coastguard Worker }
36*d9f75844SAndroid Build Coastguard Worker 
37*d9f75844SAndroid Build Coastguard Worker const double kDefaultBitratePriority = 1.0;
38*d9f75844SAndroid Build Coastguard Worker 
39*d9f75844SAndroid Build Coastguard Worker RtcpFeedback::RtcpFeedback() = default;
RtcpFeedback(RtcpFeedbackType type)40*d9f75844SAndroid Build Coastguard Worker RtcpFeedback::RtcpFeedback(RtcpFeedbackType type) : type(type) {}
RtcpFeedback(RtcpFeedbackType type,RtcpFeedbackMessageType message_type)41*d9f75844SAndroid Build Coastguard Worker RtcpFeedback::RtcpFeedback(RtcpFeedbackType type,
42*d9f75844SAndroid Build Coastguard Worker                            RtcpFeedbackMessageType message_type)
43*d9f75844SAndroid Build Coastguard Worker     : type(type), message_type(message_type) {}
44*d9f75844SAndroid Build Coastguard Worker RtcpFeedback::RtcpFeedback(const RtcpFeedback& rhs) = default;
45*d9f75844SAndroid Build Coastguard Worker RtcpFeedback::~RtcpFeedback() = default;
46*d9f75844SAndroid Build Coastguard Worker 
47*d9f75844SAndroid Build Coastguard Worker RtpCodecCapability::RtpCodecCapability() = default;
48*d9f75844SAndroid Build Coastguard Worker RtpCodecCapability::~RtpCodecCapability() = default;
49*d9f75844SAndroid Build Coastguard Worker 
50*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensionCapability::RtpHeaderExtensionCapability() = default;
RtpHeaderExtensionCapability(absl::string_view uri)51*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
52*d9f75844SAndroid Build Coastguard Worker     absl::string_view uri)
53*d9f75844SAndroid Build Coastguard Worker     : uri(uri) {}
RtpHeaderExtensionCapability(absl::string_view uri,int preferred_id)54*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
55*d9f75844SAndroid Build Coastguard Worker     absl::string_view uri,
56*d9f75844SAndroid Build Coastguard Worker     int preferred_id)
57*d9f75844SAndroid Build Coastguard Worker     : uri(uri), preferred_id(preferred_id) {}
RtpHeaderExtensionCapability(absl::string_view uri,int preferred_id,RtpTransceiverDirection direction)58*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
59*d9f75844SAndroid Build Coastguard Worker     absl::string_view uri,
60*d9f75844SAndroid Build Coastguard Worker     int preferred_id,
61*d9f75844SAndroid Build Coastguard Worker     RtpTransceiverDirection direction)
62*d9f75844SAndroid Build Coastguard Worker     : uri(uri), preferred_id(preferred_id), direction(direction) {}
63*d9f75844SAndroid Build Coastguard Worker RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() = default;
64*d9f75844SAndroid Build Coastguard Worker 
65*d9f75844SAndroid Build Coastguard Worker RtpExtension::RtpExtension() = default;
RtpExtension(absl::string_view uri,int id)66*d9f75844SAndroid Build Coastguard Worker RtpExtension::RtpExtension(absl::string_view uri, int id) : uri(uri), id(id) {}
RtpExtension(absl::string_view uri,int id,bool encrypt)67*d9f75844SAndroid Build Coastguard Worker RtpExtension::RtpExtension(absl::string_view uri, int id, bool encrypt)
68*d9f75844SAndroid Build Coastguard Worker     : uri(uri), id(id), encrypt(encrypt) {}
69*d9f75844SAndroid Build Coastguard Worker RtpExtension::~RtpExtension() = default;
70*d9f75844SAndroid Build Coastguard Worker 
71*d9f75844SAndroid Build Coastguard Worker RtpFecParameters::RtpFecParameters() = default;
RtpFecParameters(FecMechanism mechanism)72*d9f75844SAndroid Build Coastguard Worker RtpFecParameters::RtpFecParameters(FecMechanism mechanism)
73*d9f75844SAndroid Build Coastguard Worker     : mechanism(mechanism) {}
RtpFecParameters(FecMechanism mechanism,uint32_t ssrc)74*d9f75844SAndroid Build Coastguard Worker RtpFecParameters::RtpFecParameters(FecMechanism mechanism, uint32_t ssrc)
75*d9f75844SAndroid Build Coastguard Worker     : ssrc(ssrc), mechanism(mechanism) {}
76*d9f75844SAndroid Build Coastguard Worker RtpFecParameters::RtpFecParameters(const RtpFecParameters& rhs) = default;
77*d9f75844SAndroid Build Coastguard Worker RtpFecParameters::~RtpFecParameters() = default;
78*d9f75844SAndroid Build Coastguard Worker 
79*d9f75844SAndroid Build Coastguard Worker RtpRtxParameters::RtpRtxParameters() = default;
RtpRtxParameters(uint32_t ssrc)80*d9f75844SAndroid Build Coastguard Worker RtpRtxParameters::RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {}
81*d9f75844SAndroid Build Coastguard Worker RtpRtxParameters::RtpRtxParameters(const RtpRtxParameters& rhs) = default;
82*d9f75844SAndroid Build Coastguard Worker RtpRtxParameters::~RtpRtxParameters() = default;
83*d9f75844SAndroid Build Coastguard Worker 
84*d9f75844SAndroid Build Coastguard Worker RtpEncodingParameters::RtpEncodingParameters() = default;
85*d9f75844SAndroid Build Coastguard Worker RtpEncodingParameters::RtpEncodingParameters(const RtpEncodingParameters& rhs) =
86*d9f75844SAndroid Build Coastguard Worker     default;
87*d9f75844SAndroid Build Coastguard Worker RtpEncodingParameters::~RtpEncodingParameters() = default;
88*d9f75844SAndroid Build Coastguard Worker 
89*d9f75844SAndroid Build Coastguard Worker RtpCodecParameters::RtpCodecParameters() = default;
90*d9f75844SAndroid Build Coastguard Worker RtpCodecParameters::RtpCodecParameters(const RtpCodecParameters& rhs) = default;
91*d9f75844SAndroid Build Coastguard Worker RtpCodecParameters::~RtpCodecParameters() = default;
92*d9f75844SAndroid Build Coastguard Worker 
93*d9f75844SAndroid Build Coastguard Worker RtpCapabilities::RtpCapabilities() = default;
94*d9f75844SAndroid Build Coastguard Worker RtpCapabilities::~RtpCapabilities() = default;
95*d9f75844SAndroid Build Coastguard Worker 
96*d9f75844SAndroid Build Coastguard Worker RtcpParameters::RtcpParameters() = default;
97*d9f75844SAndroid Build Coastguard Worker RtcpParameters::RtcpParameters(const RtcpParameters& rhs) = default;
98*d9f75844SAndroid Build Coastguard Worker RtcpParameters::~RtcpParameters() = default;
99*d9f75844SAndroid Build Coastguard Worker 
100*d9f75844SAndroid Build Coastguard Worker RtpParameters::RtpParameters() = default;
101*d9f75844SAndroid Build Coastguard Worker RtpParameters::RtpParameters(const RtpParameters& rhs) = default;
102*d9f75844SAndroid Build Coastguard Worker RtpParameters::~RtpParameters() = default;
103*d9f75844SAndroid Build Coastguard Worker 
ToString() const104*d9f75844SAndroid Build Coastguard Worker std::string RtpExtension::ToString() const {
105*d9f75844SAndroid Build Coastguard Worker   char buf[256];
106*d9f75844SAndroid Build Coastguard Worker   rtc::SimpleStringBuilder sb(buf);
107*d9f75844SAndroid Build Coastguard Worker   sb << "{uri: " << uri;
108*d9f75844SAndroid Build Coastguard Worker   sb << ", id: " << id;
109*d9f75844SAndroid Build Coastguard Worker   if (encrypt) {
110*d9f75844SAndroid Build Coastguard Worker     sb << ", encrypt";
111*d9f75844SAndroid Build Coastguard Worker   }
112*d9f75844SAndroid Build Coastguard Worker   sb << '}';
113*d9f75844SAndroid Build Coastguard Worker   return sb.str();
114*d9f75844SAndroid Build Coastguard Worker }
115*d9f75844SAndroid Build Coastguard Worker 
116*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kEncryptHeaderExtensionsUri[];
117*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kAudioLevelUri[];
118*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kTimestampOffsetUri[];
119*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kAbsSendTimeUri[];
120*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kAbsoluteCaptureTimeUri[];
121*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kVideoRotationUri[];
122*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kVideoContentTypeUri[];
123*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kVideoTimingUri[];
124*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kGenericFrameDescriptorUri00[];
125*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kDependencyDescriptorUri[];
126*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kVideoLayersAllocationUri[];
127*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kTransportSequenceNumberUri[];
128*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kTransportSequenceNumberV2Uri[];
129*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kPlayoutDelayUri[];
130*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kColorSpaceUri[];
131*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kMidUri[];
132*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kRidUri[];
133*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kRepairedRidUri[];
134*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kVideoFrameTrackingIdUri[];
135*d9f75844SAndroid Build Coastguard Worker constexpr char RtpExtension::kCsrcAudioLevelsUri[];
136*d9f75844SAndroid Build Coastguard Worker 
137*d9f75844SAndroid Build Coastguard Worker constexpr int RtpExtension::kMinId;
138*d9f75844SAndroid Build Coastguard Worker constexpr int RtpExtension::kMaxId;
139*d9f75844SAndroid Build Coastguard Worker constexpr int RtpExtension::kMaxValueSize;
140*d9f75844SAndroid Build Coastguard Worker constexpr int RtpExtension::kOneByteHeaderExtensionMaxId;
141*d9f75844SAndroid Build Coastguard Worker constexpr int RtpExtension::kOneByteHeaderExtensionMaxValueSize;
142*d9f75844SAndroid Build Coastguard Worker 
IsSupportedForAudio(absl::string_view uri)143*d9f75844SAndroid Build Coastguard Worker bool RtpExtension::IsSupportedForAudio(absl::string_view uri) {
144*d9f75844SAndroid Build Coastguard Worker   return uri == webrtc::RtpExtension::kAudioLevelUri ||
145*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kAbsSendTimeUri ||
146*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kAbsoluteCaptureTimeUri ||
147*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
148*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri ||
149*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kMidUri ||
150*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kRidUri ||
151*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kRepairedRidUri;
152*d9f75844SAndroid Build Coastguard Worker }
153*d9f75844SAndroid Build Coastguard Worker 
IsSupportedForVideo(absl::string_view uri)154*d9f75844SAndroid Build Coastguard Worker bool RtpExtension::IsSupportedForVideo(absl::string_view uri) {
155*d9f75844SAndroid Build Coastguard Worker   return uri == webrtc::RtpExtension::kTimestampOffsetUri ||
156*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kAbsSendTimeUri ||
157*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kAbsoluteCaptureTimeUri ||
158*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kVideoRotationUri ||
159*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
160*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri ||
161*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kPlayoutDelayUri ||
162*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kVideoContentTypeUri ||
163*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kVideoTimingUri ||
164*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kMidUri ||
165*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kGenericFrameDescriptorUri00 ||
166*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kDependencyDescriptorUri ||
167*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kColorSpaceUri ||
168*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kRidUri ||
169*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kRepairedRidUri ||
170*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kVideoLayersAllocationUri ||
171*d9f75844SAndroid Build Coastguard Worker          uri == webrtc::RtpExtension::kVideoFrameTrackingIdUri;
172*d9f75844SAndroid Build Coastguard Worker }
173*d9f75844SAndroid Build Coastguard Worker 
IsEncryptionSupported(absl::string_view uri)174*d9f75844SAndroid Build Coastguard Worker bool RtpExtension::IsEncryptionSupported(absl::string_view uri) {
175*d9f75844SAndroid Build Coastguard Worker   return
176*d9f75844SAndroid Build Coastguard Worker #if defined(ENABLE_EXTERNAL_AUTH)
177*d9f75844SAndroid Build Coastguard Worker       // TODO(jbauch): Figure out a way to always allow "kAbsSendTimeUri"
178*d9f75844SAndroid Build Coastguard Worker       // here and filter out later if external auth is really used in
179*d9f75844SAndroid Build Coastguard Worker       // srtpfilter. External auth is used by Chromium and replaces the
180*d9f75844SAndroid Build Coastguard Worker       // extension header value of "kAbsSendTimeUri", so it must not be
181*d9f75844SAndroid Build Coastguard Worker       // encrypted (which can't be done by Chromium).
182*d9f75844SAndroid Build Coastguard Worker       uri != webrtc::RtpExtension::kAbsSendTimeUri &&
183*d9f75844SAndroid Build Coastguard Worker #endif
184*d9f75844SAndroid Build Coastguard Worker       uri != webrtc::RtpExtension::kEncryptHeaderExtensionsUri;
185*d9f75844SAndroid Build Coastguard Worker }
186*d9f75844SAndroid Build Coastguard Worker 
187*d9f75844SAndroid Build Coastguard Worker // Returns whether a header extension with the given URI exists.
188*d9f75844SAndroid Build Coastguard Worker // Note: This does not differentiate between encrypted and non-encrypted
189*d9f75844SAndroid Build Coastguard Worker // extensions, so use with care!
HeaderExtensionWithUriExists(const std::vector<RtpExtension> & extensions,absl::string_view uri)190*d9f75844SAndroid Build Coastguard Worker static bool HeaderExtensionWithUriExists(
191*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpExtension>& extensions,
192*d9f75844SAndroid Build Coastguard Worker     absl::string_view uri) {
193*d9f75844SAndroid Build Coastguard Worker   for (const auto& extension : extensions) {
194*d9f75844SAndroid Build Coastguard Worker     if (extension.uri == uri) {
195*d9f75844SAndroid Build Coastguard Worker       return true;
196*d9f75844SAndroid Build Coastguard Worker     }
197*d9f75844SAndroid Build Coastguard Worker   }
198*d9f75844SAndroid Build Coastguard Worker   return false;
199*d9f75844SAndroid Build Coastguard Worker }
200*d9f75844SAndroid Build Coastguard Worker 
FindHeaderExtensionByUri(const std::vector<RtpExtension> & extensions,absl::string_view uri,Filter filter)201*d9f75844SAndroid Build Coastguard Worker const RtpExtension* RtpExtension::FindHeaderExtensionByUri(
202*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpExtension>& extensions,
203*d9f75844SAndroid Build Coastguard Worker     absl::string_view uri,
204*d9f75844SAndroid Build Coastguard Worker     Filter filter) {
205*d9f75844SAndroid Build Coastguard Worker   const webrtc::RtpExtension* fallback_extension = nullptr;
206*d9f75844SAndroid Build Coastguard Worker   for (const auto& extension : extensions) {
207*d9f75844SAndroid Build Coastguard Worker     if (extension.uri != uri) {
208*d9f75844SAndroid Build Coastguard Worker       continue;
209*d9f75844SAndroid Build Coastguard Worker     }
210*d9f75844SAndroid Build Coastguard Worker 
211*d9f75844SAndroid Build Coastguard Worker     switch (filter) {
212*d9f75844SAndroid Build Coastguard Worker       case kDiscardEncryptedExtension:
213*d9f75844SAndroid Build Coastguard Worker         // We only accept an unencrypted extension.
214*d9f75844SAndroid Build Coastguard Worker         if (!extension.encrypt) {
215*d9f75844SAndroid Build Coastguard Worker           return &extension;
216*d9f75844SAndroid Build Coastguard Worker         }
217*d9f75844SAndroid Build Coastguard Worker         break;
218*d9f75844SAndroid Build Coastguard Worker 
219*d9f75844SAndroid Build Coastguard Worker       case kPreferEncryptedExtension:
220*d9f75844SAndroid Build Coastguard Worker         // We prefer an encrypted extension but we can fall back to an
221*d9f75844SAndroid Build Coastguard Worker         // unencrypted extension.
222*d9f75844SAndroid Build Coastguard Worker         if (extension.encrypt) {
223*d9f75844SAndroid Build Coastguard Worker           return &extension;
224*d9f75844SAndroid Build Coastguard Worker         } else {
225*d9f75844SAndroid Build Coastguard Worker           fallback_extension = &extension;
226*d9f75844SAndroid Build Coastguard Worker         }
227*d9f75844SAndroid Build Coastguard Worker         break;
228*d9f75844SAndroid Build Coastguard Worker 
229*d9f75844SAndroid Build Coastguard Worker       case kRequireEncryptedExtension:
230*d9f75844SAndroid Build Coastguard Worker         // We only accept an encrypted extension.
231*d9f75844SAndroid Build Coastguard Worker         if (extension.encrypt) {
232*d9f75844SAndroid Build Coastguard Worker           return &extension;
233*d9f75844SAndroid Build Coastguard Worker         }
234*d9f75844SAndroid Build Coastguard Worker         break;
235*d9f75844SAndroid Build Coastguard Worker     }
236*d9f75844SAndroid Build Coastguard Worker   }
237*d9f75844SAndroid Build Coastguard Worker 
238*d9f75844SAndroid Build Coastguard Worker   // Returning fallback extension (if any)
239*d9f75844SAndroid Build Coastguard Worker   return fallback_extension;
240*d9f75844SAndroid Build Coastguard Worker }
241*d9f75844SAndroid Build Coastguard Worker 
FindHeaderExtensionByUriAndEncryption(const std::vector<RtpExtension> & extensions,absl::string_view uri,bool encrypt)242*d9f75844SAndroid Build Coastguard Worker const RtpExtension* RtpExtension::FindHeaderExtensionByUriAndEncryption(
243*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpExtension>& extensions,
244*d9f75844SAndroid Build Coastguard Worker     absl::string_view uri,
245*d9f75844SAndroid Build Coastguard Worker     bool encrypt) {
246*d9f75844SAndroid Build Coastguard Worker   for (const auto& extension : extensions) {
247*d9f75844SAndroid Build Coastguard Worker     if (extension.uri == uri && extension.encrypt == encrypt) {
248*d9f75844SAndroid Build Coastguard Worker       return &extension;
249*d9f75844SAndroid Build Coastguard Worker     }
250*d9f75844SAndroid Build Coastguard Worker   }
251*d9f75844SAndroid Build Coastguard Worker   return nullptr;
252*d9f75844SAndroid Build Coastguard Worker }
253*d9f75844SAndroid Build Coastguard Worker 
DeduplicateHeaderExtensions(const std::vector<RtpExtension> & extensions,Filter filter)254*d9f75844SAndroid Build Coastguard Worker const std::vector<RtpExtension> RtpExtension::DeduplicateHeaderExtensions(
255*d9f75844SAndroid Build Coastguard Worker     const std::vector<RtpExtension>& extensions,
256*d9f75844SAndroid Build Coastguard Worker     Filter filter) {
257*d9f75844SAndroid Build Coastguard Worker   std::vector<RtpExtension> filtered;
258*d9f75844SAndroid Build Coastguard Worker 
259*d9f75844SAndroid Build Coastguard Worker   // If we do not discard encrypted extensions, add them first
260*d9f75844SAndroid Build Coastguard Worker   if (filter != kDiscardEncryptedExtension) {
261*d9f75844SAndroid Build Coastguard Worker     for (const auto& extension : extensions) {
262*d9f75844SAndroid Build Coastguard Worker       if (!extension.encrypt) {
263*d9f75844SAndroid Build Coastguard Worker         continue;
264*d9f75844SAndroid Build Coastguard Worker       }
265*d9f75844SAndroid Build Coastguard Worker       if (!HeaderExtensionWithUriExists(filtered, extension.uri)) {
266*d9f75844SAndroid Build Coastguard Worker         filtered.push_back(extension);
267*d9f75844SAndroid Build Coastguard Worker       }
268*d9f75844SAndroid Build Coastguard Worker     }
269*d9f75844SAndroid Build Coastguard Worker   }
270*d9f75844SAndroid Build Coastguard Worker 
271*d9f75844SAndroid Build Coastguard Worker   // If we do not require encrypted extensions, add missing, non-encrypted
272*d9f75844SAndroid Build Coastguard Worker   // extensions.
273*d9f75844SAndroid Build Coastguard Worker   if (filter != kRequireEncryptedExtension) {
274*d9f75844SAndroid Build Coastguard Worker     for (const auto& extension : extensions) {
275*d9f75844SAndroid Build Coastguard Worker       if (extension.encrypt) {
276*d9f75844SAndroid Build Coastguard Worker         continue;
277*d9f75844SAndroid Build Coastguard Worker       }
278*d9f75844SAndroid Build Coastguard Worker       if (!HeaderExtensionWithUriExists(filtered, extension.uri)) {
279*d9f75844SAndroid Build Coastguard Worker         filtered.push_back(extension);
280*d9f75844SAndroid Build Coastguard Worker       }
281*d9f75844SAndroid Build Coastguard Worker     }
282*d9f75844SAndroid Build Coastguard Worker   }
283*d9f75844SAndroid Build Coastguard Worker 
284*d9f75844SAndroid Build Coastguard Worker   // Sort the returned vector to make comparisons of header extensions reliable.
285*d9f75844SAndroid Build Coastguard Worker   // In order of priority, we sort by uri first, then encrypt and id last.
286*d9f75844SAndroid Build Coastguard Worker   std::sort(filtered.begin(), filtered.end(),
287*d9f75844SAndroid Build Coastguard Worker             [](const RtpExtension& a, const RtpExtension& b) {
288*d9f75844SAndroid Build Coastguard Worker               return std::tie(a.uri, a.encrypt, a.id) <
289*d9f75844SAndroid Build Coastguard Worker                      std::tie(b.uri, b.encrypt, b.id);
290*d9f75844SAndroid Build Coastguard Worker             });
291*d9f75844SAndroid Build Coastguard Worker 
292*d9f75844SAndroid Build Coastguard Worker   return filtered;
293*d9f75844SAndroid Build Coastguard Worker }
294*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
295