• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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