Line data Source code
1 : /*
2 : * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
12 :
13 : #include "webrtc/base/arraysize.h"
14 : #include "webrtc/base/checks.h"
15 : #include "webrtc/base/logging.h"
16 : #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
17 : #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
18 :
19 : namespace webrtc {
20 : namespace {
21 :
22 : using RtpUtility::Word32Align;
23 :
24 : struct ExtensionInfo {
25 : RTPExtensionType type;
26 : size_t value_size;
27 : const char* uri;
28 : };
29 :
30 : template <typename Extension>
31 : constexpr ExtensionInfo CreateExtensionInfo() {
32 : return {Extension::kId, Extension::kValueSizeBytes, Extension::kUri};
33 : }
34 :
35 : constexpr ExtensionInfo kExtensions[] = {
36 : CreateExtensionInfo<TransmissionOffset>(),
37 : CreateExtensionInfo<AudioLevel>(),
38 : CreateExtensionInfo<AbsoluteSendTime>(),
39 : CreateExtensionInfo<VideoOrientation>(),
40 : CreateExtensionInfo<TransportSequenceNumber>(),
41 : CreateExtensionInfo<PlayoutDelayLimits>(),
42 : CreateExtensionInfo<StreamId>(),
43 : };
44 :
45 : // Because of kRtpExtensionNone, NumberOfExtension is 1 bigger than the actual
46 : // number of known extensions.
47 : static_assert(arraysize(kExtensions) ==
48 : static_cast<int>(kRtpExtensionNumberOfExtensions) - 1,
49 : "kExtensions expect to list all known extensions");
50 :
51 0 : size_t ValueSize(RTPExtensionType type) {
52 0 : for (const ExtensionInfo& extension : kExtensions)
53 0 : if (type == extension.type)
54 0 : return extension.value_size;
55 :
56 0 : RTC_NOTREACHED();
57 0 : return 0;
58 : }
59 :
60 : } // namespace
61 :
62 : constexpr RTPExtensionType RtpHeaderExtensionMap::kInvalidType;
63 : constexpr uint8_t RtpHeaderExtensionMap::kInvalidId;
64 : constexpr uint8_t RtpHeaderExtensionMap::kMinId;
65 : constexpr uint8_t RtpHeaderExtensionMap::kMaxId;
66 :
67 0 : RtpHeaderExtensionMap::RtpHeaderExtensionMap() {
68 0 : total_values_size_bytes_ = 0;
69 0 : for (auto& type : types_)
70 0 : type = kInvalidType;
71 0 : for (auto& id : ids_)
72 0 : id = kInvalidId;
73 0 : }
74 :
75 0 : RtpHeaderExtensionMap::RtpHeaderExtensionMap(
76 0 : rtc::ArrayView<const RtpExtension> extensions)
77 0 : : RtpHeaderExtensionMap() {
78 0 : for (const RtpExtension& extension : extensions)
79 0 : RegisterByUri(extension.id, extension.uri);
80 0 : }
81 :
82 0 : bool RtpHeaderExtensionMap::RegisterByType(uint8_t id, RTPExtensionType type) {
83 0 : for (const ExtensionInfo& extension : kExtensions)
84 0 : if (type == extension.type)
85 0 : return Register(id, extension.type, extension.value_size, extension.uri);
86 0 : RTC_NOTREACHED();
87 0 : return false;
88 : }
89 :
90 0 : bool RtpHeaderExtensionMap::RegisterByUri(uint8_t id, const std::string& uri) {
91 0 : for (const ExtensionInfo& extension : kExtensions)
92 0 : if (uri == extension.uri)
93 0 : return Register(id, extension.type, extension.value_size, extension.uri);
94 0 : LOG(LS_WARNING) << "Unknown extension uri:'" << uri
95 0 : << "', id: " << static_cast<int>(id) << '.';
96 0 : return false;
97 : }
98 :
99 0 : size_t RtpHeaderExtensionMap::GetTotalLengthInBytes() const {
100 0 : if (total_values_size_bytes_ == 0)
101 0 : return 0;
102 0 : return Word32Align(kRtpOneByteHeaderLength + total_values_size_bytes_);
103 : }
104 :
105 0 : int32_t RtpHeaderExtensionMap::Deregister(RTPExtensionType type) {
106 0 : if (IsRegistered(type)) {
107 0 : uint8_t id = GetId(type);
108 0 : total_values_size_bytes_ -= (ValueSize(type) + 1);
109 0 : types_[id] = kInvalidType;
110 0 : ids_[type] = kInvalidId;
111 : }
112 0 : return 0;
113 : }
114 :
115 0 : bool RtpHeaderExtensionMap::Register(uint8_t id,
116 : RTPExtensionType type,
117 : size_t value_size,
118 : const char* uri) {
119 0 : RTC_DCHECK_GT(type, kRtpExtensionNone);
120 0 : RTC_DCHECK_LT(type, kRtpExtensionNumberOfExtensions);
121 0 : RTC_DCHECK_GE(value_size, 1U);
122 0 : RTC_DCHECK_LE(value_size, 16U);
123 :
124 0 : if (id < kMinId || id > kMaxId) {
125 0 : LOG(LS_WARNING) << "Failed to register extension uri:'" << uri
126 0 : << "' with invalid id:" << static_cast<int>(id) << ".";
127 0 : return false;
128 : }
129 :
130 0 : if (GetType(id) == type) { // Same type/id pair already registered.
131 0 : LOG(LS_VERBOSE) << "Reregistering extension uri:'" << uri
132 0 : << "', id:" << static_cast<int>(id);
133 0 : return true;
134 : }
135 :
136 0 : if (GetType(id) != kInvalidType) { // |id| used by another extension type.
137 0 : LOG(LS_WARNING) << "Failed to register extension uri:'" << uri
138 0 : << "', id:" << static_cast<int>(id)
139 0 : << ". Id already in use by extension type "
140 0 : << static_cast<int>(GetType(id));
141 0 : return false;
142 : }
143 0 : RTC_DCHECK(!IsRegistered(type));
144 :
145 0 : types_[id] = type;
146 0 : ids_[type] = id;
147 0 : total_values_size_bytes_ += (value_size + 1);
148 0 : return true;
149 : }
150 :
151 : } // namespace webrtc
|