| /* |
| * Copyright (c) 2012 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. |
| */ |
| |
| #include <assert.h> |
| |
| #include "webrtc/common_types.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h" |
| #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
| |
| namespace webrtc { |
| |
| RtpHeaderExtensionMap::RtpHeaderExtensionMap() { |
| } |
| |
| RtpHeaderExtensionMap::~RtpHeaderExtensionMap() { |
| Erase(); |
| } |
| |
| void RtpHeaderExtensionMap::Erase() { |
| while (!extensionMap_.empty()) { |
| std::map<uint8_t, HeaderExtension*>::iterator it = |
| extensionMap_.begin(); |
| delete it->second; |
| extensionMap_.erase(it); |
| } |
| } |
| |
| int32_t RtpHeaderExtensionMap::Register(const RTPExtensionType type, |
| const uint8_t id) { |
| return Register(type, id, true); |
| } |
| |
| int32_t RtpHeaderExtensionMap::RegisterInactive(const RTPExtensionType type, |
| const uint8_t id) { |
| return Register(type, id, false); |
| } |
| |
| int32_t RtpHeaderExtensionMap::Register(const RTPExtensionType type, |
| const uint8_t id, |
| bool active) { |
| if (id < 1 || id > 14) { |
| return -1; |
| } |
| std::map<uint8_t, HeaderExtension*>::iterator it = |
| extensionMap_.find(id); |
| if (it != extensionMap_.end()) { |
| if (it->second->type != type) { |
| // An extension is already registered with the same id |
| // but a different type, so return failure. |
| return -1; |
| } |
| // This extension type is already registered with this id, |
| // so return success. |
| it->second->active = active; |
| return 0; |
| } |
| extensionMap_[id] = new HeaderExtension(type, active); |
| return 0; |
| } |
| |
| bool RtpHeaderExtensionMap::SetActive(const RTPExtensionType type, |
| bool active) { |
| for (auto& kv : extensionMap_) { |
| if (kv.second->type == type) { |
| kv.second->active = active; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| int32_t RtpHeaderExtensionMap::Deregister(const RTPExtensionType type) { |
| uint8_t id; |
| if (GetId(type, &id) != 0) { |
| return 0; |
| } |
| std::map<uint8_t, HeaderExtension*>::iterator it = |
| extensionMap_.find(id); |
| assert(it != extensionMap_.end()); |
| delete it->second; |
| extensionMap_.erase(it); |
| return 0; |
| } |
| |
| bool RtpHeaderExtensionMap::IsRegistered(RTPExtensionType type) const { |
| std::map<uint8_t, HeaderExtension*>::const_iterator it = |
| extensionMap_.begin(); |
| for (; it != extensionMap_.end(); ++it) { |
| if (it->second->type == type) |
| return true; |
| } |
| return false; |
| } |
| |
| int32_t RtpHeaderExtensionMap::GetType(const uint8_t id, |
| RTPExtensionType* type) const { |
| assert(type); |
| std::map<uint8_t, HeaderExtension*>::const_iterator it = |
| extensionMap_.find(id); |
| if (it == extensionMap_.end()) { |
| return -1; |
| } |
| HeaderExtension* extension = it->second; |
| *type = extension->type; |
| return 0; |
| } |
| |
| RTPExtensionType RtpHeaderExtensionMap::GetType(uint8_t id) const { |
| auto it = extensionMap_.find(id); |
| if (it == extensionMap_.end()) { |
| return kInvalidType; |
| } |
| return it->second->type; |
| } |
| |
| int32_t RtpHeaderExtensionMap::GetId(const RTPExtensionType type, |
| uint8_t* id) const { |
| assert(id); |
| std::map<uint8_t, HeaderExtension*>::const_iterator it = |
| extensionMap_.begin(); |
| |
| while (it != extensionMap_.end()) { |
| HeaderExtension* extension = it->second; |
| if (extension->type == type) { |
| *id = it->first; |
| return 0; |
| } |
| it++; |
| } |
| return -1; |
| } |
| |
| uint8_t RtpHeaderExtensionMap::GetId(RTPExtensionType type) const { |
| for (auto kv : extensionMap_) { |
| if (kv.second->type == type) |
| return kv.first; |
| } |
| return kInvalidId; |
| } |
| |
| size_t RtpHeaderExtensionMap::GetTotalLengthInBytes() const { |
| // Get length for each extension block. |
| size_t length = 0; |
| std::map<uint8_t, HeaderExtension*>::const_iterator it = |
| extensionMap_.begin(); |
| while (it != extensionMap_.end()) { |
| HeaderExtension* extension = it->second; |
| if (extension->active) { |
| length += extension->length; |
| } |
| it++; |
| } |
| // Add RTP extension header length. |
| if (length > 0) { |
| length += kRtpOneByteHeaderLength; |
| } |
| // Pad up to nearest 32bit word. |
| length = RtpUtility::Word32Align(length); |
| return length; |
| } |
| |
| int32_t RtpHeaderExtensionMap::GetLengthUntilBlockStartInBytes( |
| const RTPExtensionType type) const { |
| uint8_t id; |
| if (GetId(type, &id) != 0) { |
| // Not registered. |
| return -1; |
| } |
| // Get length until start of extension block type. |
| uint16_t length = kRtpOneByteHeaderLength; |
| |
| std::map<uint8_t, HeaderExtension*>::const_iterator it = |
| extensionMap_.begin(); |
| while (it != extensionMap_.end()) { |
| HeaderExtension* extension = it->second; |
| if (extension->type == type) { |
| if (!extension->active) { |
| return -1; |
| } |
| break; |
| } else if (extension->active) { |
| length += extension->length; |
| } |
| it++; |
| } |
| return length; |
| } |
| |
| int32_t RtpHeaderExtensionMap::Size() const { |
| int32_t count = 0; |
| for (auto& kv : extensionMap_) { |
| if (kv.second->active) { |
| count++; |
| } |
| } |
| return count; |
| } |
| |
| RTPExtensionType RtpHeaderExtensionMap::First() const { |
| for (auto& kv : extensionMap_) { |
| if (kv.second->active) { |
| return kv.second->type; |
| } |
| } |
| |
| return kRtpExtensionNone; |
| } |
| |
| RTPExtensionType RtpHeaderExtensionMap::Next(RTPExtensionType type) const { |
| uint8_t id; |
| if (GetId(type, &id) != 0) { |
| return kRtpExtensionNone; |
| } |
| std::map<uint8_t, HeaderExtension*>::const_iterator it = |
| extensionMap_.find(id); |
| if (it == extensionMap_.end() || !it->second->active) { |
| return kRtpExtensionNone; |
| } |
| while ((++it) != extensionMap_.end()) { |
| if (it->second->active) { |
| return it->second->type; |
| } |
| } |
| |
| return kRtpExtensionNone; |
| } |
| |
| void RtpHeaderExtensionMap::GetCopy(RtpHeaderExtensionMap* map) const { |
| assert(map); |
| std::map<uint8_t, HeaderExtension*>::const_iterator it = |
| extensionMap_.begin(); |
| while (it != extensionMap_.end()) { |
| HeaderExtension* extension = it->second; |
| map->Register(extension->type, it->first, extension->active); |
| it++; |
| } |
| } |
| } // namespace webrtc |