1 /*
2  *  Copyright (c) 2012 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 <assert.h>
12 
13 #include "webrtc/common_types.h"
14 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
15 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
16 
17 namespace webrtc {
18 
RtpHeaderExtensionMap()19 RtpHeaderExtensionMap::RtpHeaderExtensionMap() {
20 }
21 
~RtpHeaderExtensionMap()22 RtpHeaderExtensionMap::~RtpHeaderExtensionMap() {
23   Erase();
24 }
25 
Erase()26 void RtpHeaderExtensionMap::Erase() {
27   while (!extensionMap_.empty()) {
28     std::map<uint8_t, HeaderExtension*>::iterator it =
29         extensionMap_.begin();
30     delete it->second;
31     extensionMap_.erase(it);
32   }
33 }
34 
Register(const RTPExtensionType type,const uint8_t id)35 int32_t RtpHeaderExtensionMap::Register(const RTPExtensionType type,
36                                         const uint8_t id) {
37   return Register(type, id, true);
38 }
39 
RegisterInactive(const RTPExtensionType type,const uint8_t id)40 int32_t RtpHeaderExtensionMap::RegisterInactive(const RTPExtensionType type,
41                                                 const uint8_t id) {
42   return Register(type, id, false);
43 }
44 
Register(const RTPExtensionType type,const uint8_t id,bool active)45 int32_t RtpHeaderExtensionMap::Register(const RTPExtensionType type,
46                                         const uint8_t id,
47                                         bool active) {
48   if (id < 1 || id > 14) {
49     return -1;
50   }
51   std::map<uint8_t, HeaderExtension*>::iterator it =
52       extensionMap_.find(id);
53   if (it != extensionMap_.end()) {
54     if (it->second->type != type) {
55       // An extension is already registered with the same id
56       // but a different type, so return failure.
57       return -1;
58     }
59     // This extension type is already registered with this id,
60     // so return success.
61     it->second->active = active;
62     return 0;
63   }
64   extensionMap_[id] = new HeaderExtension(type, active);
65   return 0;
66 }
67 
SetActive(const RTPExtensionType type,bool active)68 bool RtpHeaderExtensionMap::SetActive(const RTPExtensionType type,
69                                       bool active) {
70   for (auto& kv : extensionMap_) {
71     if (kv.second->type == type) {
72       kv.second->active = active;
73       return true;
74     }
75   }
76   return false;
77 }
78 
Deregister(const RTPExtensionType type)79 int32_t RtpHeaderExtensionMap::Deregister(const RTPExtensionType type) {
80   uint8_t id;
81   if (GetId(type, &id) != 0) {
82     return 0;
83   }
84   std::map<uint8_t, HeaderExtension*>::iterator it =
85       extensionMap_.find(id);
86   assert(it != extensionMap_.end());
87   delete it->second;
88   extensionMap_.erase(it);
89   return 0;
90 }
91 
IsRegistered(RTPExtensionType type) const92 bool RtpHeaderExtensionMap::IsRegistered(RTPExtensionType type) const {
93   std::map<uint8_t, HeaderExtension*>::const_iterator it =
94     extensionMap_.begin();
95   for (; it != extensionMap_.end(); ++it) {
96     if (it->second->type == type)
97       return true;
98   }
99   return false;
100 }
101 
GetType(const uint8_t id,RTPExtensionType * type) const102 int32_t RtpHeaderExtensionMap::GetType(const uint8_t id,
103                                        RTPExtensionType* type) const {
104   assert(type);
105   std::map<uint8_t, HeaderExtension*>::const_iterator it =
106       extensionMap_.find(id);
107   if (it == extensionMap_.end()) {
108     return -1;
109   }
110   HeaderExtension* extension = it->second;
111   *type = extension->type;
112   return 0;
113 }
114 
GetId(const RTPExtensionType type,uint8_t * id) const115 int32_t RtpHeaderExtensionMap::GetId(const RTPExtensionType type,
116                                      uint8_t* id) const {
117   assert(id);
118   std::map<uint8_t, HeaderExtension*>::const_iterator it =
119       extensionMap_.begin();
120 
121   while (it != extensionMap_.end()) {
122     HeaderExtension* extension = it->second;
123     if (extension->type == type) {
124       *id = it->first;
125       return 0;
126     }
127     it++;
128   }
129   return -1;
130 }
131 
GetTotalLengthInBytes() const132 size_t RtpHeaderExtensionMap::GetTotalLengthInBytes() const {
133   // Get length for each extension block.
134   size_t length = 0;
135   std::map<uint8_t, HeaderExtension*>::const_iterator it =
136       extensionMap_.begin();
137   while (it != extensionMap_.end()) {
138     HeaderExtension* extension = it->second;
139     if (extension->active) {
140       length += extension->length;
141     }
142     it++;
143   }
144   // Add RTP extension header length.
145   if (length > 0) {
146     length += kRtpOneByteHeaderLength;
147   }
148   // Pad up to nearest 32bit word.
149   length = RtpUtility::Word32Align(length);
150   return length;
151 }
152 
GetLengthUntilBlockStartInBytes(const RTPExtensionType type) const153 int32_t RtpHeaderExtensionMap::GetLengthUntilBlockStartInBytes(
154     const RTPExtensionType type) const {
155   uint8_t id;
156   if (GetId(type, &id) != 0) {
157     // Not registered.
158     return -1;
159   }
160   // Get length until start of extension block type.
161   uint16_t length = kRtpOneByteHeaderLength;
162 
163   std::map<uint8_t, HeaderExtension*>::const_iterator it =
164       extensionMap_.begin();
165   while (it != extensionMap_.end()) {
166     HeaderExtension* extension = it->second;
167     if (extension->type == type) {
168       if (!extension->active) {
169         return -1;
170       }
171       break;
172     } else if (extension->active) {
173       length += extension->length;
174     }
175     it++;
176   }
177   return length;
178 }
179 
Size() const180 int32_t RtpHeaderExtensionMap::Size() const {
181   int32_t count = 0;
182   for (auto& kv : extensionMap_) {
183     if (kv.second->active) {
184       count++;
185     }
186   }
187   return count;
188 }
189 
First() const190 RTPExtensionType RtpHeaderExtensionMap::First() const {
191   for (auto& kv : extensionMap_) {
192     if (kv.second->active) {
193       return kv.second->type;
194     }
195   }
196 
197   return kRtpExtensionNone;
198 }
199 
Next(RTPExtensionType type) const200 RTPExtensionType RtpHeaderExtensionMap::Next(RTPExtensionType type) const {
201   uint8_t id;
202   if (GetId(type, &id) != 0) {
203     return kRtpExtensionNone;
204   }
205   std::map<uint8_t, HeaderExtension*>::const_iterator it =
206       extensionMap_.find(id);
207   if (it == extensionMap_.end() || !it->second->active) {
208     return kRtpExtensionNone;
209   }
210   while ((++it) != extensionMap_.end()) {
211     if (it->second->active) {
212       return it->second->type;
213     }
214   }
215 
216   return kRtpExtensionNone;
217 }
218 
GetCopy(RtpHeaderExtensionMap * map) const219 void RtpHeaderExtensionMap::GetCopy(RtpHeaderExtensionMap* map) const {
220   assert(map);
221   std::map<uint8_t, HeaderExtension*>::const_iterator it =
222       extensionMap_.begin();
223   while (it != extensionMap_.end()) {
224     HeaderExtension* extension = it->second;
225     map->Register(extension->type, it->first, extension->active);
226     it++;
227   }
228 }
229 }  // namespace webrtc
230