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 "modules/rtp_rtcp/include/rtp_header_extension_map.h"
12
13 #include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
14 #include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
15 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
16 #include "rtc_base/arraysize.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/logging.h"
19
20 namespace webrtc {
21 namespace {
22
23 struct ExtensionInfo {
24 RTPExtensionType type;
25 const char* uri;
26 };
27
28 template <typename Extension>
CreateExtensionInfo()29 constexpr ExtensionInfo CreateExtensionInfo() {
30 return {Extension::kId, Extension::kUri};
31 }
32
33 constexpr ExtensionInfo kExtensions[] = {
34 CreateExtensionInfo<TransmissionOffset>(),
35 CreateExtensionInfo<AudioLevel>(),
36 CreateExtensionInfo<AbsoluteSendTime>(),
37 CreateExtensionInfo<AbsoluteCaptureTimeExtension>(),
38 CreateExtensionInfo<VideoOrientation>(),
39 CreateExtensionInfo<TransportSequenceNumber>(),
40 CreateExtensionInfo<TransportSequenceNumberV2>(),
41 CreateExtensionInfo<PlayoutDelayLimits>(),
42 CreateExtensionInfo<VideoContentTypeExtension>(),
43 CreateExtensionInfo<VideoTimingExtension>(),
44 CreateExtensionInfo<RtpStreamId>(),
45 CreateExtensionInfo<RepairedRtpStreamId>(),
46 CreateExtensionInfo<RtpMid>(),
47 CreateExtensionInfo<RtpGenericFrameDescriptorExtension00>(),
48 CreateExtensionInfo<RtpDependencyDescriptorExtension>(),
49 CreateExtensionInfo<ColorSpaceExtension>(),
50 CreateExtensionInfo<InbandComfortNoiseExtension>(),
51 };
52
53 // Because of kRtpExtensionNone, NumberOfExtension is 1 bigger than the actual
54 // number of known extensions.
55 static_assert(arraysize(kExtensions) ==
56 static_cast<int>(kRtpExtensionNumberOfExtensions) - 1,
57 "kExtensions expect to list all known extensions");
58
59 } // namespace
60
61 constexpr RTPExtensionType RtpHeaderExtensionMap::kInvalidType;
62 constexpr int RtpHeaderExtensionMap::kInvalidId;
63
RtpHeaderExtensionMap()64 RtpHeaderExtensionMap::RtpHeaderExtensionMap() : RtpHeaderExtensionMap(false) {}
65
RtpHeaderExtensionMap(bool extmap_allow_mixed)66 RtpHeaderExtensionMap::RtpHeaderExtensionMap(bool extmap_allow_mixed)
67 : extmap_allow_mixed_(extmap_allow_mixed) {
68 for (auto& id : ids_)
69 id = kInvalidId;
70 }
71
RtpHeaderExtensionMap(rtc::ArrayView<const RtpExtension> extensions)72 RtpHeaderExtensionMap::RtpHeaderExtensionMap(
73 rtc::ArrayView<const RtpExtension> extensions)
74 : RtpHeaderExtensionMap(false) {
75 for (const RtpExtension& extension : extensions)
76 RegisterByUri(extension.id, extension.uri);
77 }
78
RegisterByType(int id,RTPExtensionType type)79 bool RtpHeaderExtensionMap::RegisterByType(int id, RTPExtensionType type) {
80 for (const ExtensionInfo& extension : kExtensions)
81 if (type == extension.type)
82 return Register(id, extension.type, extension.uri);
83 RTC_NOTREACHED();
84 return false;
85 }
86
RegisterByUri(int id,absl::string_view uri)87 bool RtpHeaderExtensionMap::RegisterByUri(int id, absl::string_view uri) {
88 for (const ExtensionInfo& extension : kExtensions)
89 if (uri == extension.uri)
90 return Register(id, extension.type, extension.uri);
91 RTC_LOG(LS_WARNING) << "Unknown extension uri:'" << uri << "', id: " << id
92 << '.';
93 return false;
94 }
95
GetType(int id) const96 RTPExtensionType RtpHeaderExtensionMap::GetType(int id) const {
97 RTC_DCHECK_GE(id, RtpExtension::kMinId);
98 RTC_DCHECK_LE(id, RtpExtension::kMaxId);
99 for (int type = kRtpExtensionNone + 1; type < kRtpExtensionNumberOfExtensions;
100 ++type) {
101 if (ids_[type] == id) {
102 return static_cast<RTPExtensionType>(type);
103 }
104 }
105 return kInvalidType;
106 }
107
Deregister(RTPExtensionType type)108 int32_t RtpHeaderExtensionMap::Deregister(RTPExtensionType type) {
109 if (IsRegistered(type)) {
110 ids_[type] = kInvalidId;
111 }
112 return 0;
113 }
114
Deregister(absl::string_view uri)115 void RtpHeaderExtensionMap::Deregister(absl::string_view uri) {
116 for (const ExtensionInfo& extension : kExtensions) {
117 if (extension.uri == uri) {
118 ids_[extension.type] = kInvalidId;
119 break;
120 }
121 }
122 }
123
Register(int id,RTPExtensionType type,const char * uri)124 bool RtpHeaderExtensionMap::Register(int id,
125 RTPExtensionType type,
126 const char* uri) {
127 RTC_DCHECK_GT(type, kRtpExtensionNone);
128 RTC_DCHECK_LT(type, kRtpExtensionNumberOfExtensions);
129
130 if (id < RtpExtension::kMinId || id > RtpExtension::kMaxId) {
131 RTC_LOG(LS_WARNING) << "Failed to register extension uri:'" << uri
132 << "' with invalid id:" << id << ".";
133 return false;
134 }
135
136 RTPExtensionType registered_type = GetType(id);
137 if (registered_type == type) { // Same type/id pair already registered.
138 RTC_LOG(LS_VERBOSE) << "Reregistering extension uri:'" << uri
139 << "', id:" << id;
140 return true;
141 }
142
143 if (registered_type !=
144 kInvalidType) { // |id| used by another extension type.
145 RTC_LOG(LS_WARNING) << "Failed to register extension uri:'" << uri
146 << "', id:" << id
147 << ". Id already in use by extension type "
148 << static_cast<int>(registered_type);
149 return false;
150 }
151 RTC_DCHECK(!IsRegistered(type));
152
153 // There is a run-time check above id fits into uint8_t.
154 ids_[type] = static_cast<uint8_t>(id);
155 return true;
156 }
157
158 } // namespace webrtc
159