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 |