rtp_header_extensions.h (15322B)
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 <cstdint> 17 #include <optional> 18 #include <string> 19 #include <vector> 20 21 #include "absl/strings/string_view.h" 22 #include "api/array_view.h" 23 #include "api/rtp_headers.h" 24 #include "api/rtp_parameters.h" 25 #include "api/units/time_delta.h" 26 #include "api/units/timestamp.h" 27 #include "api/video/color_space.h" 28 #include "api/video/hdr_metadata.h" 29 #include "api/video/video_content_type.h" 30 #include "api/video/video_rotation.h" 31 #include "api/video/video_timing.h" 32 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 33 #include "rtc_base/checks.h" 34 #include "system_wrappers/include/ntp_time.h" 35 36 // This file contains class definitions for reading/writing each RTP header 37 // extension. Each class must be defined such that it is compatible with being 38 // an argument to the templated RtpPacket::GetExtension and 39 // RtpPacketToSend::SetExtension methods. New header extensions must have class 40 // names ending with "Extension", for the purpose of avoiding collisions with 41 // RTP extension information exposed in the public API of WebRTC. 42 43 namespace webrtc { 44 45 class AbsoluteSendTime { 46 public: 47 using value_type = uint32_t; 48 static constexpr RTPExtensionType kId = kRtpExtensionAbsoluteSendTime; 49 static constexpr uint8_t kValueSizeBytes = 3; 50 static constexpr absl::string_view Uri() { 51 return RtpExtension::kAbsSendTimeUri; 52 } 53 54 static bool Parse(ArrayView<const uint8_t> data, uint32_t* time_24bits); 55 static size_t ValueSize(uint32_t /* time_24bits */) { 56 return kValueSizeBytes; 57 } 58 static bool Write(ArrayView<uint8_t> data, uint32_t time_24bits); 59 60 static constexpr uint32_t To24Bits(Timestamp time) { 61 int64_t time_us = time.us() % (int64_t{1 << 6} * 1'000'000); 62 int64_t time6x18 = (time_us << 18) / 1'000'000; 63 RTC_DCHECK_GE(time6x18, 0); 64 RTC_DCHECK_LT(time6x18, 1 << 24); 65 return static_cast<uint32_t>(time6x18); 66 } 67 68 static uint32_t To24Bits(NtpTime ntp_time) { 69 uint64_t ntp_time32x32 = static_cast<uint64_t>(ntp_time); 70 return (ntp_time32x32 >> 14) & 0x00FF'FFFF; 71 } 72 73 static constexpr Timestamp ToTimestamp(uint32_t time_24bits) { 74 RTC_DCHECK_LT(time_24bits, (1 << 24)); 75 return Timestamp::Micros((time_24bits * int64_t{1'000'000}) >> 18); 76 } 77 }; 78 79 class AbsoluteCaptureTimeExtension { 80 public: 81 using value_type = AbsoluteCaptureTime; 82 static constexpr RTPExtensionType kId = kRtpExtensionAbsoluteCaptureTime; 83 static constexpr uint8_t kValueSizeBytes = 16; 84 static constexpr uint8_t kValueSizeBytesWithoutEstimatedCaptureClockOffset = 85 8; 86 static constexpr absl::string_view Uri() { 87 return RtpExtension::kAbsoluteCaptureTimeUri; 88 } 89 90 static bool Parse(ArrayView<const uint8_t> data, 91 AbsoluteCaptureTime* extension); 92 static size_t ValueSize(const AbsoluteCaptureTime& extension); 93 static bool Write(ArrayView<uint8_t> data, 94 const AbsoluteCaptureTime& extension); 95 }; 96 97 class AudioLevelExtension { 98 public: 99 using value_type = AudioLevel; 100 static constexpr RTPExtensionType kId = kRtpExtensionAudioLevel; 101 static constexpr uint8_t kValueSizeBytes = 1; 102 static constexpr absl::string_view Uri() { 103 return RtpExtension::kAudioLevelUri; 104 } 105 106 static bool Parse(ArrayView<const uint8_t> data, AudioLevel* extension); 107 static size_t ValueSize(const AudioLevel& /* extension */) { 108 return kValueSizeBytes; 109 } 110 static bool Write(ArrayView<uint8_t> data, const AudioLevel& extension); 111 }; 112 113 #if !defined(WEBRTC_MOZILLA_BUILD) 114 class CsrcAudioLevel { 115 public: 116 static constexpr RTPExtensionType kId = kRtpExtensionCsrcAudioLevel; 117 static constexpr uint8_t kMaxValueSizeBytes = 15; 118 static constexpr absl::string_view Uri() { 119 return RtpExtension::kCsrcAudioLevelsUri; 120 } 121 122 static bool Parse(ArrayView<const uint8_t> data, 123 std::vector<uint8_t>* csrc_audio_levels); 124 static size_t ValueSize(ArrayView<const uint8_t> csrc_audio_levels); 125 static bool Write(ArrayView<uint8_t> data, 126 ArrayView<const uint8_t> csrc_audio_levels); 127 }; 128 #endif 129 130 class TransmissionOffset { 131 public: 132 using value_type = int32_t; 133 static constexpr RTPExtensionType kId = kRtpExtensionTransmissionTimeOffset; 134 static constexpr uint8_t kValueSizeBytes = 3; 135 static constexpr absl::string_view Uri() { 136 return RtpExtension::kTimestampOffsetUri; 137 } 138 139 static bool Parse(ArrayView<const uint8_t> data, int32_t* rtp_time); 140 static size_t ValueSize(int32_t /* rtp_time */) { return kValueSizeBytes; } 141 static bool Write(ArrayView<uint8_t> data, int32_t rtp_time); 142 }; 143 144 class TransportSequenceNumber { 145 public: 146 using value_type = uint16_t; 147 static constexpr RTPExtensionType kId = kRtpExtensionTransportSequenceNumber; 148 static constexpr uint8_t kValueSizeBytes = 2; 149 static constexpr absl::string_view Uri() { 150 return RtpExtension::kTransportSequenceNumberUri; 151 } 152 153 static bool Parse(ArrayView<const uint8_t> data, 154 uint16_t* transport_sequence_number); 155 static size_t ValueSize(uint16_t /*transport_sequence_number*/) { 156 return kValueSizeBytes; 157 } 158 static bool Write(ArrayView<uint8_t> data, 159 uint16_t transport_sequence_number); 160 }; 161 162 class TransportSequenceNumberV2 { 163 public: 164 static constexpr RTPExtensionType kId = 165 kRtpExtensionTransportSequenceNumber02; 166 static constexpr uint8_t kValueSizeBytes = 4; 167 static constexpr uint8_t kValueSizeBytesWithoutFeedbackRequest = 2; 168 static constexpr absl::string_view Uri() { 169 return RtpExtension::kTransportSequenceNumberV2Uri; 170 } 171 172 static bool Parse(ArrayView<const uint8_t> data, 173 uint16_t* transport_sequence_number, 174 std::optional<FeedbackRequest>* feedback_request); 175 static size_t ValueSize( 176 uint16_t /*transport_sequence_number*/, 177 const std::optional<FeedbackRequest>& feedback_request) { 178 return feedback_request ? kValueSizeBytes 179 : kValueSizeBytesWithoutFeedbackRequest; 180 } 181 static bool Write(ArrayView<uint8_t> data, 182 uint16_t transport_sequence_number, 183 const std::optional<FeedbackRequest>& feedback_request); 184 185 private: 186 static constexpr uint16_t kIncludeTimestampsBit = 1 << 15; 187 }; 188 189 class VideoOrientation { 190 public: 191 using value_type = VideoRotation; 192 static constexpr RTPExtensionType kId = kRtpExtensionVideoRotation; 193 static constexpr uint8_t kValueSizeBytes = 1; 194 static constexpr absl::string_view Uri() { 195 return RtpExtension::kVideoRotationUri; 196 } 197 198 static bool Parse(ArrayView<const uint8_t> data, VideoRotation* value); 199 static size_t ValueSize(VideoRotation) { return kValueSizeBytes; } 200 static bool Write(ArrayView<uint8_t> data, VideoRotation value); 201 static bool Parse(ArrayView<const uint8_t> data, uint8_t* value); 202 static size_t ValueSize(uint8_t /* value */) { return kValueSizeBytes; } 203 static bool Write(ArrayView<uint8_t> data, uint8_t value); 204 }; 205 206 class PlayoutDelayLimits { 207 public: 208 using value_type = VideoPlayoutDelay; 209 static constexpr RTPExtensionType kId = kRtpExtensionPlayoutDelay; 210 static constexpr uint8_t kValueSizeBytes = 3; 211 static constexpr absl::string_view Uri() { 212 return RtpExtension::kPlayoutDelayUri; 213 } 214 215 // Playout delay in milliseconds. A playout delay limit (min or max) 216 // has 12 bits allocated. This allows a range of 0-4095 values which 217 // translates to a range of 0-40950 in milliseconds. 218 static constexpr TimeDelta kGranularity = TimeDelta::Millis(10); 219 // Maximum playout delay value in milliseconds. 220 static constexpr TimeDelta kMax = 0xfff * kGranularity; // 40950. 221 222 static bool Parse(ArrayView<const uint8_t> data, 223 VideoPlayoutDelay* playout_delay); 224 static size_t ValueSize(const VideoPlayoutDelay&) { return kValueSizeBytes; } 225 static bool Write(ArrayView<uint8_t> data, 226 const VideoPlayoutDelay& playout_delay); 227 }; 228 229 class VideoContentTypeExtension { 230 public: 231 using value_type = VideoContentType; 232 static constexpr RTPExtensionType kId = kRtpExtensionVideoContentType; 233 static constexpr uint8_t kValueSizeBytes = 1; 234 static constexpr absl::string_view Uri() { 235 return RtpExtension::kVideoContentTypeUri; 236 } 237 238 static bool Parse(ArrayView<const uint8_t> data, 239 VideoContentType* content_type); 240 static size_t ValueSize(VideoContentType) { return kValueSizeBytes; } 241 static bool Write(ArrayView<uint8_t> data, VideoContentType content_type); 242 }; 243 244 class VideoTimingExtension { 245 public: 246 using value_type = VideoSendTiming; 247 static constexpr RTPExtensionType kId = kRtpExtensionVideoTiming; 248 static constexpr uint8_t kValueSizeBytes = 13; 249 static constexpr absl::string_view Uri() { 250 return RtpExtension::kVideoTimingUri; 251 } 252 253 // Offsets of the fields in the RTP header extension, counting from the first 254 // byte after the one-byte header. 255 static constexpr uint8_t kFlagsOffset = 0; 256 static constexpr uint8_t kEncodeStartDeltaOffset = 1; 257 static constexpr uint8_t kEncodeFinishDeltaOffset = 3; 258 static constexpr uint8_t kPacketizationFinishDeltaOffset = 5; 259 static constexpr uint8_t kPacerExitDeltaOffset = 7; 260 static constexpr uint8_t kNetworkTimestampDeltaOffset = 9; 261 static constexpr uint8_t kNetwork2TimestampDeltaOffset = 11; 262 263 static bool Parse(ArrayView<const uint8_t> data, VideoSendTiming* timing); 264 static size_t ValueSize(const VideoSendTiming&) { return kValueSizeBytes; } 265 static bool Write(ArrayView<uint8_t> data, const VideoSendTiming& timing); 266 267 static size_t ValueSize(uint16_t /* time_delta_ms */, uint8_t /* idx */) { 268 return kValueSizeBytes; 269 } 270 // Writes only single time delta to position idx. 271 static bool Write(ArrayView<uint8_t> data, 272 uint16_t time_delta_ms, 273 uint8_t offset); 274 }; 275 276 class ColorSpaceExtension { 277 public: 278 using value_type = ColorSpace; 279 static constexpr RTPExtensionType kId = kRtpExtensionColorSpace; 280 static constexpr uint8_t kValueSizeBytes = 28; 281 static constexpr uint8_t kValueSizeBytesWithoutHdrMetadata = 4; 282 static constexpr absl::string_view Uri() { 283 return RtpExtension::kColorSpaceUri; 284 } 285 286 static bool Parse(ArrayView<const uint8_t> data, ColorSpace* color_space); 287 static size_t ValueSize(const ColorSpace& color_space) { 288 return color_space.hdr_metadata() ? kValueSizeBytes 289 : kValueSizeBytesWithoutHdrMetadata; 290 } 291 static bool Write(ArrayView<uint8_t> data, const ColorSpace& color_space); 292 293 private: 294 static constexpr int kChromaticityDenominator = 50000; // 0.00002 resolution. 295 static constexpr int kLuminanceMaxDenominator = 1; // 1 resolution. 296 static constexpr int kLuminanceMinDenominator = 10000; // 0.0001 resolution. 297 298 static uint8_t CombineRangeAndChromaSiting( 299 ColorSpace::RangeID range, 300 ColorSpace::ChromaSiting chroma_siting_horizontal, 301 ColorSpace::ChromaSiting chroma_siting_vertical); 302 static size_t ParseHdrMetadata(ArrayView<const uint8_t> data, 303 HdrMetadata* hdr_metadata); 304 static size_t ParseChromaticity(const uint8_t* data, 305 HdrMasteringMetadata::Chromaticity* p); 306 static size_t ParseLuminance(const uint8_t* data, float* f, int denominator); 307 static size_t WriteHdrMetadata(ArrayView<uint8_t> data, 308 const HdrMetadata& hdr_metadata); 309 static size_t WriteChromaticity(uint8_t* data, 310 const HdrMasteringMetadata::Chromaticity& p); 311 static size_t WriteLuminance(uint8_t* data, float f, int denominator); 312 }; 313 314 #if defined(WEBRTC_MOZILLA_BUILD) 315 class CsrcAudioLevel { 316 public: 317 static constexpr RTPExtensionType kId = kRtpExtensionCsrcAudioLevel; 318 static constexpr absl::string_view Uri() { 319 return RtpExtension::kCsrcAudioLevelsUri; 320 } 321 static constexpr const char* kUri = 322 "urn:ietf:params:rtp-hdrext:csrc-audio-level"; 323 324 static bool Parse(webrtc::ArrayView<const uint8_t> data, 325 CsrcAudioLevelList* csrcAudioLevels); 326 static size_t ValueSize(const CsrcAudioLevelList& csrcAudioLevels); 327 static bool Write(webrtc::ArrayView<uint8_t> data, 328 const CsrcAudioLevelList& csrcAudioLevels); 329 }; 330 #endif 331 332 // Base extension class for RTP header extensions which are strings. 333 // Subclasses must defined kId and kUri static constexpr members. 334 class BaseRtpStringExtension { 335 public: 336 using value_type = std::string; 337 // String RTP header extensions are limited to 16 bytes because it is the 338 // maximum length that can be encoded with one-byte header extensions. 339 static constexpr uint8_t kMaxValueSizeBytes = 16; 340 341 static bool Parse(ArrayView<const uint8_t> data, std::string* str); 342 static size_t ValueSize(absl::string_view str) { return str.size(); } 343 static bool Write(ArrayView<uint8_t> data, absl::string_view str); 344 }; 345 346 class RtpStreamId : public BaseRtpStringExtension { 347 public: 348 static constexpr RTPExtensionType kId = kRtpExtensionRtpStreamId; 349 static constexpr absl::string_view Uri() { return RtpExtension::kRidUri; } 350 }; 351 352 class RepairedRtpStreamId : public BaseRtpStringExtension { 353 public: 354 static constexpr RTPExtensionType kId = kRtpExtensionRepairedRtpStreamId; 355 static constexpr absl::string_view Uri() { 356 return RtpExtension::kRepairedRidUri; 357 } 358 }; 359 360 class RtpMid : public BaseRtpStringExtension { 361 public: 362 static constexpr RTPExtensionType kId = kRtpExtensionMid; 363 static constexpr absl::string_view Uri() { return RtpExtension::kMidUri; } 364 }; 365 366 class InbandComfortNoiseExtension { 367 public: 368 using value_type = std::optional<uint8_t>; 369 370 static constexpr RTPExtensionType kId = kRtpExtensionInbandComfortNoise; 371 static constexpr uint8_t kValueSizeBytes = 1; 372 static constexpr const char kUri[] = 373 "http://www.webrtc.org/experiments/rtp-hdrext/inband-cn"; 374 static constexpr absl::string_view Uri() { return kUri; } 375 376 static bool Parse(ArrayView<const uint8_t> data, 377 std::optional<uint8_t>* level); 378 static size_t ValueSize(std::optional<uint8_t> /* level */) { 379 return kValueSizeBytes; 380 } 381 static bool Write(ArrayView<uint8_t> data, std::optional<uint8_t> level); 382 }; 383 384 class VideoFrameTrackingIdExtension { 385 public: 386 using value_type = uint16_t; 387 static constexpr RTPExtensionType kId = kRtpExtensionVideoFrameTrackingId; 388 static constexpr uint8_t kValueSizeBytes = 2; 389 static constexpr absl::string_view Uri() { 390 return RtpExtension::kVideoFrameTrackingIdUri; 391 } 392 393 static bool Parse(ArrayView<const uint8_t> data, 394 uint16_t* video_frame_tracking_id); 395 static size_t ValueSize(uint16_t /*video_frame_tracking_id*/) { 396 return kValueSizeBytes; 397 } 398 static bool Write(ArrayView<uint8_t> data, uint16_t video_frame_tracking_id); 399 }; 400 401 } // namespace webrtc 402 #endif // MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_