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