1 /*
2  *  Copyright (c) 2016 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 #ifndef MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_
11 #define MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #include <string>
17 
18 #include "api/array_view.h"
19 #include "api/rtp_headers.h"
20 #include "api/video/color_space.h"
21 #include "api/video/video_content_type.h"
22 #include "api/video/video_rotation.h"
23 #include "api/video/video_timing.h"
24 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
25 
26 namespace webrtc {
27 
28 class AbsoluteSendTime {
29  public:
30   using value_type = uint32_t;
31   static constexpr RTPExtensionType kId = kRtpExtensionAbsoluteSendTime;
32   static constexpr uint8_t kValueSizeBytes = 3;
33   static constexpr const char kUri[] =
34       "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
35 
36   static bool Parse(rtc::ArrayView<const uint8_t> data, uint32_t* time_24bits);
ValueSize(uint32_t time_24bits)37   static size_t ValueSize(uint32_t time_24bits) { return kValueSizeBytes; }
38   static bool Write(rtc::ArrayView<uint8_t> data, uint32_t time_24bits);
39 
MsTo24Bits(int64_t time_ms)40   static constexpr uint32_t MsTo24Bits(int64_t time_ms) {
41     return static_cast<uint32_t>(((time_ms << 18) + 500) / 1000) & 0x00FFFFFF;
42   }
43 };
44 
45 class AbsoluteCaptureTimeExtension {
46  public:
47   using value_type = AbsoluteCaptureTime;
48   static constexpr RTPExtensionType kId = kRtpExtensionAbsoluteCaptureTime;
49   static constexpr uint8_t kValueSizeBytes = 16;
50   static constexpr uint8_t kValueSizeBytesWithoutEstimatedCaptureClockOffset =
51       8;
52   static constexpr const char kUri[] =
53       "http://www.webrtc.org/experiments/rtp-hdrext/abs-capture-time";
54 
55   static bool Parse(rtc::ArrayView<const uint8_t> data,
56                     AbsoluteCaptureTime* extension);
57   static size_t ValueSize(const AbsoluteCaptureTime& extension);
58   static bool Write(rtc::ArrayView<uint8_t> data,
59                     const AbsoluteCaptureTime& extension);
60 };
61 
62 class AudioLevel {
63  public:
64   static constexpr RTPExtensionType kId = kRtpExtensionAudioLevel;
65   static constexpr uint8_t kValueSizeBytes = 1;
66   static constexpr const char kUri[] =
67       "urn:ietf:params:rtp-hdrext:ssrc-audio-level";
68 
69   static bool Parse(rtc::ArrayView<const uint8_t> data,
70                     bool* voice_activity,
71                     uint8_t* audio_level);
ValueSize(bool voice_activity,uint8_t audio_level)72   static size_t ValueSize(bool voice_activity, uint8_t audio_level) {
73     return kValueSizeBytes;
74   }
75   static bool Write(rtc::ArrayView<uint8_t> data,
76                     bool voice_activity,
77                     uint8_t audio_level);
78 };
79 
80 class TransmissionOffset {
81  public:
82   using value_type = int32_t;
83   static constexpr RTPExtensionType kId = kRtpExtensionTransmissionTimeOffset;
84   static constexpr uint8_t kValueSizeBytes = 3;
85   static constexpr const char kUri[] = "urn:ietf:params:rtp-hdrext:toffset";
86 
87   static bool Parse(rtc::ArrayView<const uint8_t> data, int32_t* rtp_time);
ValueSize(int32_t rtp_time)88   static size_t ValueSize(int32_t rtp_time) { return kValueSizeBytes; }
89   static bool Write(rtc::ArrayView<uint8_t> data, int32_t rtp_time);
90 };
91 
92 class TransportSequenceNumber {
93  public:
94   using value_type = uint16_t;
95   static constexpr RTPExtensionType kId = kRtpExtensionTransportSequenceNumber;
96   static constexpr uint8_t kValueSizeBytes = 2;
97   static constexpr const char kUri[] =
98       "http://www.ietf.org/id/"
99       "draft-holmer-rmcat-transport-wide-cc-extensions-01";
100   static bool Parse(rtc::ArrayView<const uint8_t> data,
101                     uint16_t* transport_sequence_number);
ValueSize(uint16_t)102   static size_t ValueSize(uint16_t /*transport_sequence_number*/) {
103     return kValueSizeBytes;
104   }
105   static bool Write(rtc::ArrayView<uint8_t> data,
106                     uint16_t transport_sequence_number);
107 };
108 
109 class TransportSequenceNumberV2 {
110  public:
111   static constexpr RTPExtensionType kId =
112       kRtpExtensionTransportSequenceNumber02;
113   static constexpr uint8_t kValueSizeBytes = 4;
114   static constexpr uint8_t kValueSizeBytesWithoutFeedbackRequest = 2;
115   static constexpr const char kUri[] =
116       "http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02";
117   static bool Parse(rtc::ArrayView<const uint8_t> data,
118                     uint16_t* transport_sequence_number,
119                     absl::optional<FeedbackRequest>* feedback_request);
ValueSize(uint16_t,const absl::optional<FeedbackRequest> & feedback_request)120   static size_t ValueSize(
121       uint16_t /*transport_sequence_number*/,
122       const absl::optional<FeedbackRequest>& feedback_request) {
123     return feedback_request ? kValueSizeBytes
124                             : kValueSizeBytesWithoutFeedbackRequest;
125   }
126   static bool Write(rtc::ArrayView<uint8_t> data,
127                     uint16_t transport_sequence_number,
128                     const absl::optional<FeedbackRequest>& feedback_request);
129 
130  private:
131   static constexpr uint16_t kIncludeTimestampsBit = 1 << 15;
132 };
133 
134 class VideoOrientation {
135  public:
136   using value_type = VideoRotation;
137   static constexpr RTPExtensionType kId = kRtpExtensionVideoRotation;
138   static constexpr uint8_t kValueSizeBytes = 1;
139   static constexpr const char kUri[] = "urn:3gpp:video-orientation";
140 
141   static bool Parse(rtc::ArrayView<const uint8_t> data, VideoRotation* value);
ValueSize(VideoRotation)142   static size_t ValueSize(VideoRotation) { return kValueSizeBytes; }
143   static bool Write(rtc::ArrayView<uint8_t> data, VideoRotation value);
144   static bool Parse(rtc::ArrayView<const uint8_t> data, uint8_t* value);
ValueSize(uint8_t value)145   static size_t ValueSize(uint8_t value) { return kValueSizeBytes; }
146   static bool Write(rtc::ArrayView<uint8_t> data, uint8_t value);
147 };
148 
149 class PlayoutDelayLimits {
150  public:
151   using value_type = VideoPlayoutDelay;
152   static constexpr RTPExtensionType kId = kRtpExtensionPlayoutDelay;
153   static constexpr uint8_t kValueSizeBytes = 3;
154   static constexpr const char kUri[] =
155       "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay";
156 
157   // Playout delay in milliseconds. A playout delay limit (min or max)
158   // has 12 bits allocated. This allows a range of 0-4095 values which
159   // translates to a range of 0-40950 in milliseconds.
160   static constexpr int kGranularityMs = 10;
161   // Maximum playout delay value in milliseconds.
162   static constexpr int kMaxMs = 0xfff * kGranularityMs;  // 40950.
163 
164   static bool Parse(rtc::ArrayView<const uint8_t> data,
165                     VideoPlayoutDelay* playout_delay);
ValueSize(const VideoPlayoutDelay &)166   static size_t ValueSize(const VideoPlayoutDelay&) { return kValueSizeBytes; }
167   static bool Write(rtc::ArrayView<uint8_t> data,
168                     const VideoPlayoutDelay& playout_delay);
169 };
170 
171 class VideoContentTypeExtension {
172  public:
173   using value_type = VideoContentType;
174   static constexpr RTPExtensionType kId = kRtpExtensionVideoContentType;
175   static constexpr uint8_t kValueSizeBytes = 1;
176   static constexpr const char kUri[] =
177       "http://www.webrtc.org/experiments/rtp-hdrext/video-content-type";
178 
179   static bool Parse(rtc::ArrayView<const uint8_t> data,
180                     VideoContentType* content_type);
ValueSize(VideoContentType)181   static size_t ValueSize(VideoContentType) { return kValueSizeBytes; }
182   static bool Write(rtc::ArrayView<uint8_t> data,
183                     VideoContentType content_type);
184 };
185 
186 class VideoTimingExtension {
187  public:
188   using value_type = VideoSendTiming;
189   static constexpr RTPExtensionType kId = kRtpExtensionVideoTiming;
190   static constexpr uint8_t kValueSizeBytes = 13;
191   static constexpr const char kUri[] =
192       "http://www.webrtc.org/experiments/rtp-hdrext/video-timing";
193 
194   // Offsets of the fields in the RTP header extension, counting from the first
195   // byte after the one-byte header.
196   static constexpr uint8_t kFlagsOffset = 0;
197   static constexpr uint8_t kEncodeStartDeltaOffset = 1;
198   static constexpr uint8_t kEncodeFinishDeltaOffset = 3;
199   static constexpr uint8_t kPacketizationFinishDeltaOffset = 5;
200   static constexpr uint8_t kPacerExitDeltaOffset = 7;
201   static constexpr uint8_t kNetworkTimestampDeltaOffset = 9;
202   static constexpr uint8_t kNetwork2TimestampDeltaOffset = 11;
203 
204   static bool Parse(rtc::ArrayView<const uint8_t> data,
205                     VideoSendTiming* timing);
ValueSize(const VideoSendTiming &)206   static size_t ValueSize(const VideoSendTiming&) { return kValueSizeBytes; }
207   static bool Write(rtc::ArrayView<uint8_t> data,
208                     const VideoSendTiming& timing);
209 
ValueSize(uint16_t time_delta_ms,uint8_t idx)210   static size_t ValueSize(uint16_t time_delta_ms, uint8_t idx) {
211     return kValueSizeBytes;
212   }
213   // Writes only single time delta to position idx.
214   static bool Write(rtc::ArrayView<uint8_t> data,
215                     uint16_t time_delta_ms,
216                     uint8_t offset);
217 };
218 
219 class ColorSpaceExtension {
220  public:
221   using value_type = ColorSpace;
222   static constexpr RTPExtensionType kId = kRtpExtensionColorSpace;
223   static constexpr uint8_t kValueSizeBytes = 28;
224   static constexpr uint8_t kValueSizeBytesWithoutHdrMetadata = 4;
225   static constexpr const char kUri[] =
226       "http://www.webrtc.org/experiments/rtp-hdrext/color-space";
227 
228   static bool Parse(rtc::ArrayView<const uint8_t> data,
229                     ColorSpace* color_space);
ValueSize(const ColorSpace & color_space)230   static size_t ValueSize(const ColorSpace& color_space) {
231     return color_space.hdr_metadata() ? kValueSizeBytes
232                                       : kValueSizeBytesWithoutHdrMetadata;
233   }
234   static bool Write(rtc::ArrayView<uint8_t> data,
235                     const ColorSpace& color_space);
236 
237  private:
238   static constexpr int kChromaticityDenominator = 50000;  // 0.00002 resolution.
239   static constexpr int kLuminanceMaxDenominator = 1;      // 1 resolution.
240   static constexpr int kLuminanceMinDenominator = 10000;  // 0.0001 resolution.
241 
242   static uint8_t CombineRangeAndChromaSiting(
243       ColorSpace::RangeID range,
244       ColorSpace::ChromaSiting chroma_siting_horizontal,
245       ColorSpace::ChromaSiting chroma_siting_vertical);
246   static size_t ParseHdrMetadata(rtc::ArrayView<const uint8_t> data,
247                                  HdrMetadata* hdr_metadata);
248   static size_t ParseChromaticity(const uint8_t* data,
249                                   HdrMasteringMetadata::Chromaticity* p);
250   static size_t ParseLuminance(const uint8_t* data, float* f, int denominator);
251   static size_t WriteHdrMetadata(rtc::ArrayView<uint8_t> data,
252                                  const HdrMetadata& hdr_metadata);
253   static size_t WriteChromaticity(uint8_t* data,
254                                   const HdrMasteringMetadata::Chromaticity& p);
255   static size_t WriteLuminance(uint8_t* data, float f, int denominator);
256 };
257 
258 class CsrcAudioLevel {
259  public:
260   static constexpr RTPExtensionType kId = kRtpExtensionCsrcAudioLevel;
261   static constexpr const char* kUri =
262       "urn:ietf:params:rtp-hdrext:csrc-audio-level";
263 
264   static bool Parse(rtc::ArrayView<const uint8_t> data,
265                     CsrcAudioLevelList* csrcAudioLevels);
266   static size_t ValueSize(const CsrcAudioLevelList& csrcAudioLevels);
267   static bool Write(rtc::ArrayView<uint8_t> data, const CsrcAudioLevelList& csrcAudioLevels);
268 };
269 
270 // Base extension class for RTP header extensions which are strings.
271 // Subclasses must defined kId and kUri static constexpr members.
272 class BaseRtpStringExtension {
273  public:
274   using value_type = std::string;
275   // String RTP header extensions are limited to 16 bytes because it is the
276   // maximum length that can be encoded with one-byte header extensions.
277   static constexpr uint8_t kMaxValueSizeBytes = 16;
278 
279   static bool Parse(rtc::ArrayView<const uint8_t> data, std::string* str);
ValueSize(const std::string & str)280   static size_t ValueSize(const std::string& str) { return str.size(); }
281   static bool Write(rtc::ArrayView<uint8_t> data, const std::string& str);
282 };
283 
284 class RtpStreamId : public BaseRtpStringExtension {
285  public:
286   static constexpr RTPExtensionType kId = kRtpExtensionRtpStreamId;
287   static constexpr const char kUri[] =
288       "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
289 };
290 
291 class RepairedRtpStreamId : public BaseRtpStringExtension {
292  public:
293   static constexpr RTPExtensionType kId = kRtpExtensionRepairedRtpStreamId;
294   static constexpr const char kUri[] =
295       "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";
296 };
297 
298 class RtpMid : public BaseRtpStringExtension {
299  public:
300   static constexpr RTPExtensionType kId = kRtpExtensionMid;
301   static constexpr const char kUri[] = "urn:ietf:params:rtp-hdrext:sdes:mid";
302 };
303 
304 class InbandComfortNoiseExtension {
305  public:
306   using value_type = absl::optional<uint8_t>;
307 
308   static constexpr RTPExtensionType kId = kRtpExtensionInbandComfortNoise;
309   static constexpr uint8_t kValueSizeBytes = 1;
310   static constexpr const char kUri[] =
311       "http://www.webrtc.org/experiments/rtp-hdrext/inband-cn";
312 
313   static bool Parse(rtc::ArrayView<const uint8_t> data,
314                     absl::optional<uint8_t>* level);
ValueSize(absl::optional<uint8_t> level)315   static size_t ValueSize(absl::optional<uint8_t> level) {
316     return kValueSizeBytes;
317   }
318   static bool Write(rtc::ArrayView<uint8_t> data,
319                     absl::optional<uint8_t> level);
320 };
321 
322 }  // namespace webrtc
323 #endif  // MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_
324