| /* |
| * 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 "modules/rtp_rtcp/include/rtp_header_extension_map.h" |
| |
| #include "modules/rtp_rtcp/source/rtp_header_extensions.h" |
| #include "rtc_base/arraysize.h" |
| #include "rtc_base/checks.h" |
| #include "rtc_base/logging.h" |
| |
| namespace webrtc { |
| namespace { |
| |
| struct ExtensionInfo { |
| RTPExtensionType type; |
| const char* uri; |
| }; |
| |
| template <typename Extension> |
| constexpr ExtensionInfo CreateExtensionInfo() { |
| return {Extension::kId, Extension::kUri}; |
| } |
| |
| constexpr ExtensionInfo kExtensions[] = { |
| CreateExtensionInfo<TransmissionOffset>(), |
| CreateExtensionInfo<AudioLevel>(), |
| CreateExtensionInfo<AbsoluteSendTime>(), |
| CreateExtensionInfo<VideoOrientation>(), |
| CreateExtensionInfo<TransportSequenceNumber>(), |
| CreateExtensionInfo<PlayoutDelayLimits>(), |
| CreateExtensionInfo<VideoContentTypeExtension>(), |
| CreateExtensionInfo<VideoTimingExtension>(), |
| CreateExtensionInfo<RtpStreamId>(), |
| CreateExtensionInfo<RepairedRtpStreamId>(), |
| CreateExtensionInfo<RtpMid>(), |
| }; |
| |
| // 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"); |
| |
| } // namespace |
| |
| constexpr RTPExtensionType RtpHeaderExtensionMap::kInvalidType; |
| constexpr int RtpHeaderExtensionMap::kInvalidId; |
| constexpr int RtpHeaderExtensionMap::kMinId; |
| constexpr int RtpHeaderExtensionMap::kMaxId; |
| |
| RtpHeaderExtensionMap::RtpHeaderExtensionMap() { |
| for (auto& type : types_) |
| type = kInvalidType; |
| for (auto& id : ids_) |
| id = kInvalidId; |
| } |
| |
| RtpHeaderExtensionMap::RtpHeaderExtensionMap( |
| rtc::ArrayView<const RtpExtension> extensions) |
| : RtpHeaderExtensionMap() { |
| for (const RtpExtension& extension : extensions) |
| RegisterByUri(extension.id, extension.uri); |
| } |
| |
| bool RtpHeaderExtensionMap::RegisterByType(int id, RTPExtensionType type) { |
| for (const ExtensionInfo& extension : kExtensions) |
| if (type == extension.type) |
| return Register(id, extension.type, extension.uri); |
| RTC_NOTREACHED(); |
| return false; |
| } |
| |
| bool RtpHeaderExtensionMap::RegisterByUri(int id, const std::string& uri) { |
| for (const ExtensionInfo& extension : kExtensions) |
| if (uri == extension.uri) |
| return Register(id, extension.type, extension.uri); |
| RTC_LOG(LS_WARNING) << "Unknown extension uri:'" << uri << "', id: " << id |
| << '.'; |
| return false; |
| } |
| |
| size_t RtpHeaderExtensionMap::GetTotalLengthInBytes( |
| rtc::ArrayView<const RtpExtensionSize> extensions) const { |
| // Header size of the extension block, see RFC3550 Section 5.3.1 |
| static constexpr size_t kRtpOneByteHeaderLength = 4; |
| // Header size of each individual extension, see RFC5285 Section 4.2 |
| static constexpr size_t kExtensionHeaderLength = 1; |
| size_t values_size = 0; |
| for (const RtpExtensionSize& extension : extensions) { |
| if (IsRegistered(extension.type)) |
| values_size += extension.value_size + kExtensionHeaderLength; |
| } |
| if (values_size == 0) |
| return 0; |
| size_t size = kRtpOneByteHeaderLength + values_size; |
| // Round up to the nearest size that is a multiple of 4. |
| // Which is same as round down (size + 3). |
| return size + 3 - (size + 3) % 4; |
| } |
| |
| int32_t RtpHeaderExtensionMap::Deregister(RTPExtensionType type) { |
| if (IsRegistered(type)) { |
| uint8_t id = GetId(type); |
| types_[id] = kInvalidType; |
| ids_[type] = kInvalidId; |
| } |
| return 0; |
| } |
| |
| bool RtpHeaderExtensionMap::Register(int id, |
| RTPExtensionType type, |
| const char* uri) { |
| RTC_DCHECK_GT(type, kRtpExtensionNone); |
| RTC_DCHECK_LT(type, kRtpExtensionNumberOfExtensions); |
| |
| if (id < kMinId || id > kMaxId) { |
| RTC_LOG(LS_WARNING) << "Failed to register extension uri:'" << uri |
| << "' with invalid id:" << id << "."; |
| return false; |
| } |
| |
| if (GetType(id) == type) { // Same type/id pair already registered. |
| RTC_LOG(LS_VERBOSE) << "Reregistering extension uri:'" << uri |
| << "', id:" << id; |
| return true; |
| } |
| |
| if (GetType(id) != kInvalidType) { // |id| used by another extension type. |
| RTC_LOG(LS_WARNING) << "Failed to register extension uri:'" << uri |
| << "', id:" << id |
| << ". Id already in use by extension type " |
| << static_cast<int>(GetType(id)); |
| return false; |
| } |
| RTC_DCHECK(!IsRegistered(type)); |
| |
| types_[id] = type; |
| // There is a run-time check above id fits into uint8_t. |
| ids_[type] = static_cast<uint8_t>(id); |
| return true; |
| } |
| |
| } // namespace webrtc |