| 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 7fdff3498532ad43aef92592cafc94f463371b6d..b7c73062759df159f35ecbfc2b01646307db1331 100644
|
| --- a/webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc
|
| +++ b/webrtc/modules/rtp_rtcp/source/rtp_header_extension.cc
|
| @@ -8,148 +8,143 @@
|
| * be found in the AUTHORS file in the root of the source tree.
|
| */
|
|
|
| -#include <assert.h>
|
| +#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
|
|
|
| +#include "webrtc/base/arraysize.h"
|
| #include "webrtc/base/checks.h"
|
| -#include "webrtc/common_types.h"
|
| -#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.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 {
|
|
|
| -constexpr uint8_t RtpHeaderExtensionMap::kInvalidId;
|
| +using RtpUtility::Word32Align;
|
|
|
| -RtpHeaderExtensionMap::RtpHeaderExtensionMap() {
|
| +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() {
|
| - Erase();
|
| -}
|
| +constexpr ExtensionInfo kExtensions[] = {
|
| + CreateExtensionInfo<TransmissionOffset>(),
|
| + CreateExtensionInfo<AudioLevel>(),
|
| + CreateExtensionInfo<AbsoluteSendTime>(),
|
| + CreateExtensionInfo<VideoOrientation>(),
|
| + CreateExtensionInfo<TransportSequenceNumber>(),
|
| + CreateExtensionInfo<PlayoutDelayLimits>(),
|
| +};
|
|
|
| -void RtpHeaderExtensionMap::Erase() {
|
| - while (!extensionMap_.empty()) {
|
| - std::map<uint8_t, HeaderExtension*>::iterator it =
|
| - extensionMap_.begin();
|
| - delete it->second;
|
| - extensionMap_.erase(it);
|
| - }
|
| -}
|
| +// 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");
|
|
|
| -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);
|
| +size_t ValueSize(RTPExtensionType type) {
|
| + for (const ExtensionInfo& extension : kExtensions)
|
| + if (type == extension.type)
|
| + return extension.value_size;
|
| +
|
| + RTC_NOTREACHED();
|
| return 0;
|
| }
|
|
|
| -int32_t RtpHeaderExtensionMap::Deregister(const RTPExtensionType type) {
|
| - uint8_t id;
|
| - if (GetId(type, &id) != 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;
|
| +}
|
| +
|
| +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();
|
| + 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;
|
| +}
|
| +
|
| +size_t RtpHeaderExtensionMap::GetTotalLengthInBytes() const {
|
| + if (total_values_size_bytes_ == 0)
|
| return 0;
|
| + return Word32Align(kRtpOneByteHeaderLength + total_values_size_bytes_);
|
| +}
|
| +
|
| +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;
|
| }
|
| - 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;
|
| +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;
|
| }
|
| - return false;
|
| +
|
| + 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;
|
| }
|
|
|
| -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;
|
| - 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::Size() const {
|
| - return extensionMap_.size();
|
| -}
|
| -
|
| -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++;
|
| - }
|
| -}
|
| } // namespace webrtc
|
|
|