xref: /aosp_15_r20/external/webrtc/pc/used_ids.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2019 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 #ifndef PC_USED_IDS_H_
11*d9f75844SAndroid Build Coastguard Worker #define PC_USED_IDS_H_
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <set>
14*d9f75844SAndroid Build Coastguard Worker #include <vector>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include "api/rtp_parameters.h"
17*d9f75844SAndroid Build Coastguard Worker #include "media/base/codec.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
20*d9f75844SAndroid Build Coastguard Worker 
21*d9f75844SAndroid Build Coastguard Worker namespace cricket {
22*d9f75844SAndroid Build Coastguard Worker template <typename IdStruct>
23*d9f75844SAndroid Build Coastguard Worker class UsedIds {
24*d9f75844SAndroid Build Coastguard Worker  public:
UsedIds(int min_allowed_id,int max_allowed_id)25*d9f75844SAndroid Build Coastguard Worker   UsedIds(int min_allowed_id, int max_allowed_id)
26*d9f75844SAndroid Build Coastguard Worker       : min_allowed_id_(min_allowed_id),
27*d9f75844SAndroid Build Coastguard Worker         max_allowed_id_(max_allowed_id),
28*d9f75844SAndroid Build Coastguard Worker         next_id_(max_allowed_id) {}
~UsedIds()29*d9f75844SAndroid Build Coastguard Worker   virtual ~UsedIds() {}
30*d9f75844SAndroid Build Coastguard Worker 
31*d9f75844SAndroid Build Coastguard Worker   // Loops through all Id in `ids` and changes its id if it is
32*d9f75844SAndroid Build Coastguard Worker   // already in use by another IdStruct. Call this methods with all Id
33*d9f75844SAndroid Build Coastguard Worker   // in a session description to make sure no duplicate ids exists.
34*d9f75844SAndroid Build Coastguard Worker   // Note that typename Id must be a type of IdStruct.
35*d9f75844SAndroid Build Coastguard Worker   template <typename Id>
FindAndSetIdUsed(std::vector<Id> * ids)36*d9f75844SAndroid Build Coastguard Worker   void FindAndSetIdUsed(std::vector<Id>* ids) {
37*d9f75844SAndroid Build Coastguard Worker     for (const Id& id : *ids) {
38*d9f75844SAndroid Build Coastguard Worker       FindAndSetIdUsed(&id);
39*d9f75844SAndroid Build Coastguard Worker     }
40*d9f75844SAndroid Build Coastguard Worker   }
41*d9f75844SAndroid Build Coastguard Worker 
42*d9f75844SAndroid Build Coastguard Worker   // Finds and sets an unused id if the `idstruct` id is already in use.
FindAndSetIdUsed(IdStruct * idstruct)43*d9f75844SAndroid Build Coastguard Worker   void FindAndSetIdUsed(IdStruct* idstruct) {
44*d9f75844SAndroid Build Coastguard Worker     const int original_id = idstruct->id;
45*d9f75844SAndroid Build Coastguard Worker     int new_id = idstruct->id;
46*d9f75844SAndroid Build Coastguard Worker 
47*d9f75844SAndroid Build Coastguard Worker     if (original_id > max_allowed_id_ || original_id < min_allowed_id_) {
48*d9f75844SAndroid Build Coastguard Worker       // If the original id is not in range - this is an id that can't be
49*d9f75844SAndroid Build Coastguard Worker       // dynamically changed.
50*d9f75844SAndroid Build Coastguard Worker       return;
51*d9f75844SAndroid Build Coastguard Worker     }
52*d9f75844SAndroid Build Coastguard Worker 
53*d9f75844SAndroid Build Coastguard Worker     if (IsIdUsed(original_id)) {
54*d9f75844SAndroid Build Coastguard Worker       new_id = FindUnusedId();
55*d9f75844SAndroid Build Coastguard Worker       // Duplicate id found. Reassign from the original id to the new.
56*d9f75844SAndroid Build Coastguard Worker       idstruct->id = new_id;
57*d9f75844SAndroid Build Coastguard Worker     }
58*d9f75844SAndroid Build Coastguard Worker     SetIdUsed(new_id);
59*d9f75844SAndroid Build Coastguard Worker   }
60*d9f75844SAndroid Build Coastguard Worker 
61*d9f75844SAndroid Build Coastguard Worker  protected:
IsIdUsed(int new_id)62*d9f75844SAndroid Build Coastguard Worker   virtual bool IsIdUsed(int new_id) {
63*d9f75844SAndroid Build Coastguard Worker     return id_set_.find(new_id) != id_set_.end();
64*d9f75844SAndroid Build Coastguard Worker   }
65*d9f75844SAndroid Build Coastguard Worker   const int min_allowed_id_;
66*d9f75844SAndroid Build Coastguard Worker   const int max_allowed_id_;
67*d9f75844SAndroid Build Coastguard Worker 
68*d9f75844SAndroid Build Coastguard Worker  private:
69*d9f75844SAndroid Build Coastguard Worker   // Returns the first unused id in reverse order.
70*d9f75844SAndroid Build Coastguard Worker   // This hopefully reduces the risk of more collisions. We want to change the
71*d9f75844SAndroid Build Coastguard Worker   // default ids as little as possible. This function is virtual and can be
72*d9f75844SAndroid Build Coastguard Worker   // overriden if the search for unused IDs should follow a specific pattern.
FindUnusedId()73*d9f75844SAndroid Build Coastguard Worker   virtual int FindUnusedId() {
74*d9f75844SAndroid Build Coastguard Worker     while (IsIdUsed(next_id_) && next_id_ >= min_allowed_id_) {
75*d9f75844SAndroid Build Coastguard Worker       --next_id_;
76*d9f75844SAndroid Build Coastguard Worker     }
77*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(next_id_ >= min_allowed_id_);
78*d9f75844SAndroid Build Coastguard Worker     return next_id_;
79*d9f75844SAndroid Build Coastguard Worker   }
80*d9f75844SAndroid Build Coastguard Worker 
SetIdUsed(int new_id)81*d9f75844SAndroid Build Coastguard Worker   void SetIdUsed(int new_id) {
82*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(new_id >= min_allowed_id_);
83*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(new_id <= max_allowed_id_);
84*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!IsIdUsed(new_id));
85*d9f75844SAndroid Build Coastguard Worker     id_set_.insert(new_id);
86*d9f75844SAndroid Build Coastguard Worker   }
87*d9f75844SAndroid Build Coastguard Worker   int next_id_;
88*d9f75844SAndroid Build Coastguard Worker   std::set<int> id_set_;
89*d9f75844SAndroid Build Coastguard Worker };
90*d9f75844SAndroid Build Coastguard Worker 
91*d9f75844SAndroid Build Coastguard Worker // Helper class used for finding duplicate RTP payload types among audio, video
92*d9f75844SAndroid Build Coastguard Worker // and data codecs. When bundle is used the payload types may not collide.
93*d9f75844SAndroid Build Coastguard Worker class UsedPayloadTypes : public UsedIds<Codec> {
94*d9f75844SAndroid Build Coastguard Worker  public:
UsedPayloadTypes()95*d9f75844SAndroid Build Coastguard Worker   UsedPayloadTypes()
96*d9f75844SAndroid Build Coastguard Worker       : UsedIds<Codec>(kFirstDynamicPayloadTypeLowerRange,
97*d9f75844SAndroid Build Coastguard Worker                        kLastDynamicPayloadTypeUpperRange) {}
98*d9f75844SAndroid Build Coastguard Worker 
99*d9f75844SAndroid Build Coastguard Worker  protected:
IsIdUsed(int new_id)100*d9f75844SAndroid Build Coastguard Worker   bool IsIdUsed(int new_id) override {
101*d9f75844SAndroid Build Coastguard Worker     // Range marked for RTCP avoidance is "used".
102*d9f75844SAndroid Build Coastguard Worker     if (new_id > kLastDynamicPayloadTypeLowerRange &&
103*d9f75844SAndroid Build Coastguard Worker         new_id < kFirstDynamicPayloadTypeUpperRange)
104*d9f75844SAndroid Build Coastguard Worker       return true;
105*d9f75844SAndroid Build Coastguard Worker     return UsedIds<Codec>::IsIdUsed(new_id);
106*d9f75844SAndroid Build Coastguard Worker   }
107*d9f75844SAndroid Build Coastguard Worker 
108*d9f75844SAndroid Build Coastguard Worker  private:
109*d9f75844SAndroid Build Coastguard Worker   static const int kFirstDynamicPayloadTypeLowerRange = 35;
110*d9f75844SAndroid Build Coastguard Worker   static const int kLastDynamicPayloadTypeLowerRange = 63;
111*d9f75844SAndroid Build Coastguard Worker 
112*d9f75844SAndroid Build Coastguard Worker   static const int kFirstDynamicPayloadTypeUpperRange = 96;
113*d9f75844SAndroid Build Coastguard Worker   static const int kLastDynamicPayloadTypeUpperRange = 127;
114*d9f75844SAndroid Build Coastguard Worker };
115*d9f75844SAndroid Build Coastguard Worker 
116*d9f75844SAndroid Build Coastguard Worker // Helper class used for finding duplicate RTP Header extension ids among
117*d9f75844SAndroid Build Coastguard Worker // audio and video extensions.
118*d9f75844SAndroid Build Coastguard Worker class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> {
119*d9f75844SAndroid Build Coastguard Worker  public:
120*d9f75844SAndroid Build Coastguard Worker   enum class IdDomain {
121*d9f75844SAndroid Build Coastguard Worker     // Only allocate IDs that fit in one-byte header extensions.
122*d9f75844SAndroid Build Coastguard Worker     kOneByteOnly,
123*d9f75844SAndroid Build Coastguard Worker     // Prefer to allocate one-byte header extension IDs, but overflow to
124*d9f75844SAndroid Build Coastguard Worker     // two-byte if none are left.
125*d9f75844SAndroid Build Coastguard Worker     kTwoByteAllowed,
126*d9f75844SAndroid Build Coastguard Worker   };
127*d9f75844SAndroid Build Coastguard Worker 
UsedRtpHeaderExtensionIds(IdDomain id_domain)128*d9f75844SAndroid Build Coastguard Worker   explicit UsedRtpHeaderExtensionIds(IdDomain id_domain)
129*d9f75844SAndroid Build Coastguard Worker       : UsedIds<webrtc::RtpExtension>(
130*d9f75844SAndroid Build Coastguard Worker             webrtc::RtpExtension::kMinId,
131*d9f75844SAndroid Build Coastguard Worker             id_domain == IdDomain::kTwoByteAllowed
132*d9f75844SAndroid Build Coastguard Worker                 ? webrtc::RtpExtension::kMaxId
133*d9f75844SAndroid Build Coastguard Worker                 : webrtc::RtpExtension::kOneByteHeaderExtensionMaxId),
134*d9f75844SAndroid Build Coastguard Worker         id_domain_(id_domain),
135*d9f75844SAndroid Build Coastguard Worker         next_extension_id_(webrtc::RtpExtension::kOneByteHeaderExtensionMaxId) {
136*d9f75844SAndroid Build Coastguard Worker   }
137*d9f75844SAndroid Build Coastguard Worker 
138*d9f75844SAndroid Build Coastguard Worker  private:
139*d9f75844SAndroid Build Coastguard Worker   // Returns the first unused id in reverse order from the max id of one byte
140*d9f75844SAndroid Build Coastguard Worker   // header extensions. This hopefully reduce the risk of more collisions. We
141*d9f75844SAndroid Build Coastguard Worker   // want to change the default ids as little as possible. If no unused id is
142*d9f75844SAndroid Build Coastguard Worker   // found and two byte header extensions are enabled (i.e.,
143*d9f75844SAndroid Build Coastguard Worker   // `extmap_allow_mixed_` is true), search for unused ids from 15 to 255.
FindUnusedId()144*d9f75844SAndroid Build Coastguard Worker   int FindUnusedId() override {
145*d9f75844SAndroid Build Coastguard Worker     if (next_extension_id_ <=
146*d9f75844SAndroid Build Coastguard Worker         webrtc::RtpExtension::kOneByteHeaderExtensionMaxId) {
147*d9f75844SAndroid Build Coastguard Worker       // First search in reverse order from the max id of one byte header
148*d9f75844SAndroid Build Coastguard Worker       // extensions.
149*d9f75844SAndroid Build Coastguard Worker       while (IsIdUsed(next_extension_id_) &&
150*d9f75844SAndroid Build Coastguard Worker              next_extension_id_ >= min_allowed_id_) {
151*d9f75844SAndroid Build Coastguard Worker         --next_extension_id_;
152*d9f75844SAndroid Build Coastguard Worker       }
153*d9f75844SAndroid Build Coastguard Worker     }
154*d9f75844SAndroid Build Coastguard Worker 
155*d9f75844SAndroid Build Coastguard Worker     if (id_domain_ == IdDomain::kTwoByteAllowed) {
156*d9f75844SAndroid Build Coastguard Worker       if (next_extension_id_ < min_allowed_id_) {
157*d9f75844SAndroid Build Coastguard Worker         // We have searched among all one-byte IDs without finding an unused ID,
158*d9f75844SAndroid Build Coastguard Worker         // continue at the first two-byte ID.
159*d9f75844SAndroid Build Coastguard Worker         next_extension_id_ =
160*d9f75844SAndroid Build Coastguard Worker             webrtc::RtpExtension::kOneByteHeaderExtensionMaxId + 1;
161*d9f75844SAndroid Build Coastguard Worker       }
162*d9f75844SAndroid Build Coastguard Worker 
163*d9f75844SAndroid Build Coastguard Worker       if (next_extension_id_ >
164*d9f75844SAndroid Build Coastguard Worker           webrtc::RtpExtension::kOneByteHeaderExtensionMaxId) {
165*d9f75844SAndroid Build Coastguard Worker         while (IsIdUsed(next_extension_id_) &&
166*d9f75844SAndroid Build Coastguard Worker                next_extension_id_ <= max_allowed_id_) {
167*d9f75844SAndroid Build Coastguard Worker           ++next_extension_id_;
168*d9f75844SAndroid Build Coastguard Worker         }
169*d9f75844SAndroid Build Coastguard Worker       }
170*d9f75844SAndroid Build Coastguard Worker     }
171*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(next_extension_id_ >= min_allowed_id_);
172*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(next_extension_id_ <= max_allowed_id_);
173*d9f75844SAndroid Build Coastguard Worker     return next_extension_id_;
174*d9f75844SAndroid Build Coastguard Worker   }
175*d9f75844SAndroid Build Coastguard Worker 
176*d9f75844SAndroid Build Coastguard Worker   const IdDomain id_domain_;
177*d9f75844SAndroid Build Coastguard Worker   int next_extension_id_;
178*d9f75844SAndroid Build Coastguard Worker };
179*d9f75844SAndroid Build Coastguard Worker 
180*d9f75844SAndroid Build Coastguard Worker }  // namespace cricket
181*d9f75844SAndroid Build Coastguard Worker 
182*d9f75844SAndroid Build Coastguard Worker #endif  // PC_USED_IDS_H_
183