| /* |
| * Copyright 2019 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| #ifndef PC_USED_IDS_H_ |
| #define PC_USED_IDS_H_ |
| |
| #include <set> |
| #include <vector> |
| |
| #include "media/base/codec.h" |
| #include "rtc_base/checks.h" |
| |
| namespace webrtc { |
| template <typename IdStruct> |
| class UsedIds { |
| public: |
| UsedIds(int min_allowed_id, int max_allowed_id) |
| : min_allowed_id_(min_allowed_id), |
| max_allowed_id_(max_allowed_id), |
| next_id_(max_allowed_id) {} |
| virtual ~UsedIds() {} |
| |
| // Loops through all Id in `ids` and changes its id if it is |
| // already in use by another IdStruct. Call this methods with all Id |
| // in a session description to make sure no duplicate ids exists. |
| // Note that typename Id must be a type of IdStruct. |
| template <typename Id> |
| void FindAndSetIdUsed(std::vector<Id>* ids) { |
| for (const Id& id : *ids) { |
| FindAndSetIdUsed(&id); |
| } |
| } |
| |
| // Finds and sets an unused id if the `idstruct` id is already in use. |
| void FindAndSetIdUsed(IdStruct* idstruct) { |
| const int original_id = idstruct->id; |
| int new_id = idstruct->id; |
| |
| if (original_id > max_allowed_id_ || original_id < min_allowed_id_) { |
| // If the original id is not in range - this is an id that can't be |
| // dynamically changed. |
| return; |
| } |
| |
| if (IsIdUsed(original_id)) { |
| new_id = FindUnusedId(); |
| // Duplicate id found. Reassign from the original id to the new. |
| idstruct->id = new_id; |
| } |
| SetIdUsed(new_id); |
| } |
| |
| protected: |
| virtual bool IsIdUsed(int new_id) { |
| return id_set_.find(new_id) != id_set_.end(); |
| } |
| const int min_allowed_id_; |
| const int max_allowed_id_; |
| |
| private: |
| // Returns the first unused id in reverse order. |
| // This hopefully reduces the risk of more collisions. We want to change the |
| // default ids as little as possible. This function is virtual and can be |
| // overriden if the search for unused IDs should follow a specific pattern. |
| virtual int FindUnusedId() { |
| while (IsIdUsed(next_id_) && next_id_ >= min_allowed_id_) { |
| --next_id_; |
| } |
| RTC_DCHECK(next_id_ >= min_allowed_id_); |
| return next_id_; |
| } |
| |
| void SetIdUsed(int new_id) { |
| RTC_DCHECK(new_id >= min_allowed_id_); |
| RTC_DCHECK(new_id <= max_allowed_id_); |
| RTC_DCHECK(!IsIdUsed(new_id)); |
| id_set_.insert(new_id); |
| } |
| int next_id_; |
| std::set<int> id_set_; |
| }; |
| |
| // Helper class used for finding duplicate RTP payload types among audio, video |
| // and data codecs. When bundle is used the payload types may not collide. |
| class UsedPayloadTypes : public UsedIds<Codec> { |
| public: |
| UsedPayloadTypes() |
| : UsedIds<Codec>(kFirstDynamicPayloadTypeLowerRange, |
| kLastDynamicPayloadTypeUpperRange) {} |
| |
| // Check if a payload type is valid. The range [64-95] is forbidden |
| // when rtcp-mux is used. |
| static bool IsIdValid(Codec codec, bool rtcp_mux) { |
| if (rtcp_mux && (codec.id > kLastDynamicPayloadTypeLowerRange && |
| codec.id < kFirstDynamicPayloadTypeUpperRange)) { |
| return false; |
| } |
| return codec.id >= 0 && codec.id <= kLastDynamicPayloadTypeUpperRange; |
| } |
| |
| protected: |
| bool IsIdUsed(int new_id) override { |
| // Range marked for RTCP avoidance is "used". |
| if (new_id > kLastDynamicPayloadTypeLowerRange && |
| new_id < kFirstDynamicPayloadTypeUpperRange) |
| return true; |
| return UsedIds<Codec>::IsIdUsed(new_id); |
| } |
| |
| private: |
| static const int kFirstDynamicPayloadTypeLowerRange = 35; |
| static const int kLastDynamicPayloadTypeLowerRange = 63; |
| |
| static const int kFirstDynamicPayloadTypeUpperRange = 96; |
| static const int kLastDynamicPayloadTypeUpperRange = 127; |
| }; |
| |
| } // namespace webrtc |
| |
| #endif // PC_USED_IDS_H_ |