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 = PlayoutDelay; 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 PlayoutDelay* playout_delay); ValueSize(const PlayoutDelay &)166 static size_t ValueSize(const PlayoutDelay&) { return kValueSizeBytes; } 167 static bool Write(rtc::ArrayView<uint8_t> data, 168 const PlayoutDelay& 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 // Base extension class for RTP header extensions which are strings. 259 // Subclasses must defined kId and kUri static constexpr members. 260 class BaseRtpStringExtension { 261 public: 262 using value_type = std::string; 263 // String RTP header extensions are limited to 16 bytes because it is the 264 // maximum length that can be encoded with one-byte header extensions. 265 static constexpr uint8_t kMaxValueSizeBytes = 16; 266 267 static bool Parse(rtc::ArrayView<const uint8_t> data, std::string* str); ValueSize(const std::string & str)268 static size_t ValueSize(const std::string& str) { return str.size(); } 269 static bool Write(rtc::ArrayView<uint8_t> data, const std::string& str); 270 }; 271 272 class RtpStreamId : public BaseRtpStringExtension { 273 public: 274 static constexpr RTPExtensionType kId = kRtpExtensionRtpStreamId; 275 static constexpr const char kUri[] = 276 "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id"; 277 }; 278 279 class RepairedRtpStreamId : public BaseRtpStringExtension { 280 public: 281 static constexpr RTPExtensionType kId = kRtpExtensionRepairedRtpStreamId; 282 static constexpr const char kUri[] = 283 "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id"; 284 }; 285 286 class RtpMid : public BaseRtpStringExtension { 287 public: 288 static constexpr RTPExtensionType kId = kRtpExtensionMid; 289 static constexpr const char kUri[] = "urn:ietf:params:rtp-hdrext:sdes:mid"; 290 }; 291 292 class InbandComfortNoiseExtension { 293 public: 294 using value_type = absl::optional<uint8_t>; 295 296 static constexpr RTPExtensionType kId = kRtpExtensionInbandComfortNoise; 297 static constexpr uint8_t kValueSizeBytes = 1; 298 static constexpr const char kUri[] = 299 "http://www.webrtc.org/experiments/rtp-hdrext/inband-cn"; 300 301 static bool Parse(rtc::ArrayView<const uint8_t> data, 302 absl::optional<uint8_t>* level); ValueSize(absl::optional<uint8_t> level)303 static size_t ValueSize(absl::optional<uint8_t> level) { 304 return kValueSizeBytes; 305 } 306 static bool Write(rtc::ArrayView<uint8_t> data, 307 absl::optional<uint8_t> level); 308 }; 309 310 } // namespace webrtc 311 #endif // MODULES_RTP_RTCP_SOURCE_RTP_HEADER_EXTENSIONS_H_ 312