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 19 RtpHeaderExtensionMap::RtpHeaderExtensionMap() { 20 } 21 22 RtpHeaderExtensionMap::~RtpHeaderExtensionMap() { 23 Erase(); 24 } 25 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 35 int32_t RtpHeaderExtensionMap::Register(const RTPExtensionType type, 36 const uint8_t id) { 37 return Register(type, id, true); 38 } 39 40 int32_t RtpHeaderExtensionMap::RegisterInactive(const RTPExtensionType type, 41 const uint8_t id) { 42 return Register(type, id, false); 43 } 44 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 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 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 92 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 102 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 115 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 132 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 153 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 180 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 190 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 200 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 219 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