| Index: webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc
|
| diff --git a/webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc b/webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc
|
| index b7c73062759df159f35ecbfc2b01646307db1331..7fdff3498532ad43aef92592cafc94f463371b6d 100644
|
| --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc
|
| +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc
|
| @@ -8,143 +8,148 @@
|
| * be found in the AUTHORS file in the root of the source tree.
|
| */
|
|
|
| +#include <assert.h>
|
| +
|
| +#include "webrtc/base/checks.h"
|
| +#include "webrtc/common_types.h"
|
| #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
|
| -
|
| -#include "webrtc/base/arraysize.h"
|
| -#include "webrtc/base/checks.h"
|
| -#include "webrtc/base/logging.h"
|
| -#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
|
| #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
|
|
|
| namespace webrtc {
|
| -namespace {
|
|
|
| -using RtpUtility::Word32Align;
|
| +constexpr uint8_t RtpHeaderExtensionMap::kInvalidId;
|
|
|
| -struct ExtensionInfo {
|
| - RTPExtensionType type;
|
| - size_t value_size;
|
| - const char* uri;
|
| -};
|
| -
|
| -template <typename Extension>
|
| -constexpr ExtensionInfo CreateExtensionInfo() {
|
| - return {Extension::kId, Extension::kValueSizeBytes, Extension::kUri};
|
| +RtpHeaderExtensionMap::RtpHeaderExtensionMap() {
|
| }
|
|
|
| -constexpr ExtensionInfo kExtensions[] = {
|
| - CreateExtensionInfo<TransmissionOffset>(),
|
| - CreateExtensionInfo<AudioLevel>(),
|
| - CreateExtensionInfo<AbsoluteSendTime>(),
|
| - CreateExtensionInfo<VideoOrientation>(),
|
| - CreateExtensionInfo<TransportSequenceNumber>(),
|
| - CreateExtensionInfo<PlayoutDelayLimits>(),
|
| -};
|
| +RtpHeaderExtensionMap::~RtpHeaderExtensionMap() {
|
| + Erase();
|
| +}
|
|
|
| -// Because of kRtpExtensionNone, NumberOfExtension is 1 bigger than the actual
|
| -// number of known extensions.
|
| -static_assert(arraysize(kExtensions) ==
|
| - static_cast<int>(kRtpExtensionNumberOfExtensions) - 1,
|
| - "kExtensions expect to list all known extensions");
|
| +void RtpHeaderExtensionMap::Erase() {
|
| + while (!extensionMap_.empty()) {
|
| + std::map<uint8_t, HeaderExtension*>::iterator it =
|
| + extensionMap_.begin();
|
| + delete it->second;
|
| + extensionMap_.erase(it);
|
| + }
|
| +}
|
|
|
| -size_t ValueSize(RTPExtensionType type) {
|
| - for (const ExtensionInfo& extension : kExtensions)
|
| - if (type == extension.type)
|
| - return extension.value_size;
|
| -
|
| - RTC_NOTREACHED();
|
| +int32_t RtpHeaderExtensionMap::Register(RTPExtensionType type, uint8_t id) {
|
| + 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.
|
| + return 0;
|
| + }
|
| + RTC_DCHECK_EQ(kInvalidId, GetId(type));
|
| + extensionMap_[id] = new HeaderExtension(type);
|
| return 0;
|
| }
|
|
|
| -} // namespace
|
| -
|
| -constexpr RTPExtensionType RtpHeaderExtensionMap::kInvalidType;
|
| -constexpr uint8_t RtpHeaderExtensionMap::kInvalidId;
|
| -constexpr uint8_t RtpHeaderExtensionMap::kMinId;
|
| -constexpr uint8_t RtpHeaderExtensionMap::kMaxId;
|
| -
|
| -RtpHeaderExtensionMap::RtpHeaderExtensionMap() {
|
| - total_values_size_bytes_ = 0;
|
| - for (auto& type : types_)
|
| - type = kInvalidType;
|
| - for (auto& id : ids_)
|
| - id = kInvalidId;
|
| +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;
|
| }
|
|
|
| -RtpHeaderExtensionMap::RtpHeaderExtensionMap(
|
| - std::initializer_list<RtpExtension> extensions)
|
| - : RtpHeaderExtensionMap() {
|
| - for (const RtpExtension& extension : extensions)
|
| - RegisterByUri(extension.id, extension.uri);
|
| -}
|
| -
|
| -bool RtpHeaderExtensionMap::RegisterByType(uint8_t id, RTPExtensionType type) {
|
| - for (const ExtensionInfo& extension : kExtensions)
|
| - if (type == extension.type)
|
| - return Register(id, extension.type, extension.value_size, extension.uri);
|
| - RTC_NOTREACHED();
|
| +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;
|
| }
|
|
|
| -bool RtpHeaderExtensionMap::RegisterByUri(uint8_t id, const std::string& uri) {
|
| - for (const ExtensionInfo& extension : kExtensions)
|
| - if (uri == extension.uri)
|
| - return Register(id, extension.type, extension.value_size, extension.uri);
|
| - LOG(LS_WARNING) << "Unknown extension uri:'" << uri
|
| - << "', id: " << static_cast<int>(id) << '.';
|
| - 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 {
|
| - if (total_values_size_bytes_ == 0)
|
| - return 0;
|
| - return Word32Align(kRtpOneByteHeaderLength + total_values_size_bytes_);
|
| + // Get length for each extension block.
|
| + size_t length = 0;
|
| + for (const auto& kv : extensionMap_)
|
| + length += kv.second->length;
|
| + // 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::Deregister(RTPExtensionType type) {
|
| - if (IsRegistered(type)) {
|
| - uint8_t id = GetId(type);
|
| - total_values_size_bytes_ -= (ValueSize(type) + 1);
|
| - types_[id] = kInvalidType;
|
| - ids_[type] = kInvalidId;
|
| - }
|
| - return 0;
|
| +int32_t RtpHeaderExtensionMap::Size() const {
|
| + return extensionMap_.size();
|
| }
|
|
|
| -bool RtpHeaderExtensionMap::Register(uint8_t id,
|
| - RTPExtensionType type,
|
| - size_t value_size,
|
| - const char* uri) {
|
| - RTC_DCHECK_GT(type, kRtpExtensionNone);
|
| - RTC_DCHECK_LT(type, kRtpExtensionNumberOfExtensions);
|
| - RTC_DCHECK_GE(value_size, 1U);
|
| - RTC_DCHECK_LE(value_size, 16U);
|
| -
|
| - if (id < kMinId || id > kMaxId) {
|
| - LOG(LS_WARNING) << "Failed to register extension uri:'" << uri
|
| - << "' with invalid id:" << static_cast<int>(id) << ".";
|
| - return false;
|
| +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);
|
| + it++;
|
| }
|
| -
|
| - if (GetType(id) == type) { // Same type/id pair already registered.
|
| - LOG(LS_VERBOSE) << "Reregistering extension uri:'" << uri
|
| - << "', id:" << static_cast<int>(id);
|
| - return true;
|
| - }
|
| -
|
| - if (GetType(id) != kInvalidType) { // |id| used by another extension type.
|
| - LOG(LS_WARNING) << "Failed to register extension uri:'" << uri
|
| - << "', id:" << static_cast<int>(id)
|
| - << ". Id already in use by extension type "
|
| - << static_cast<int>(GetType(id));
|
| - return false;
|
| - }
|
| - RTC_DCHECK(!IsRegistered(type));
|
| -
|
| - types_[id] = type;
|
| - ids_[type] = id;
|
| - total_values_size_bytes_ += (value_size + 1);
|
| - return true;
|
| }
|
| -
|
| } // namespace webrtc
|
|
|