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 
11 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
12 
13 #include "modules/rtp_rtcp/include/rtp_cvo.h"
14 #include "modules/rtp_rtcp/source/byte_io.h"
15 #include "rtc_base/checks.h"
16 #include "rtc_base/logging.h"
17 
18 namespace webrtc {
19 // Absolute send time in RTP streams.
20 //
21 // The absolute send time is signaled to the receiver in-band using the
22 // general mechanism for RTP header extensions [RFC5285]. The payload
23 // of this extension (the transmitted value) is a 24-bit unsigned integer
24 // containing the sender's current time in seconds as a fixed point number
25 // with 18 bits fractional part.
26 //
27 // The form of the absolute send time extension block:
28 //
29 //    0                   1                   2                   3
30 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
31 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 //   |  ID   | len=2 |              absolute send time               |
33 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 constexpr RTPExtensionType AbsoluteSendTime::kId;
35 constexpr uint8_t AbsoluteSendTime::kValueSizeBytes;
36 constexpr const char AbsoluteSendTime::kUri[];
37 
Parse(rtc::ArrayView<const uint8_t> data,uint32_t * time_24bits)38 bool AbsoluteSendTime::Parse(rtc::ArrayView<const uint8_t> data,
39                              uint32_t* time_24bits) {
40   if (data.size() != 3)
41     return false;
42   *time_24bits = ByteReader<uint32_t, 3>::ReadBigEndian(data.data());
43   return true;
44 }
45 
Write(uint8_t * data,uint32_t time_24bits)46 bool AbsoluteSendTime::Write(uint8_t* data, uint32_t time_24bits) {
47   RTC_DCHECK_LE(time_24bits, 0x00FFFFFF);
48   ByteWriter<uint32_t, 3>::WriteBigEndian(data, time_24bits);
49   return true;
50 }
51 
52 // An RTP Header Extension for Client-to-Mixer Audio Level Indication
53 //
54 // https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
55 //
56 // The form of the audio level extension block:
57 //
58 //    0                   1
59 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
60 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 //   |  ID   | len=0 |V|   level     |
62 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 //
64 constexpr RTPExtensionType AudioLevel::kId;
65 constexpr uint8_t AudioLevel::kValueSizeBytes;
66 constexpr const char AudioLevel::kUri[];
67 
Parse(rtc::ArrayView<const uint8_t> data,bool * voice_activity,uint8_t * audio_level)68 bool AudioLevel::Parse(rtc::ArrayView<const uint8_t> data,
69                        bool* voice_activity,
70                        uint8_t* audio_level) {
71   if (data.size() != 1)
72     return false;
73   *voice_activity = (data[0] & 0x80) != 0;
74   *audio_level = data[0] & 0x7F;
75   return true;
76 }
77 
Write(uint8_t * data,bool voice_activity,uint8_t audio_level)78 bool AudioLevel::Write(uint8_t* data,
79                        bool voice_activity,
80                        uint8_t audio_level) {
81   RTC_CHECK_LE(audio_level, 0x7f);
82   data[0] = (voice_activity ? 0x80 : 0x00) | audio_level;
83   return true;
84 }
85 
86 // From RFC 5450: Transmission Time Offsets in RTP Streams.
87 //
88 // The transmission time is signaled to the receiver in-band using the
89 // general mechanism for RTP header extensions [RFC5285]. The payload
90 // of this extension (the transmitted value) is a 24-bit signed integer.
91 // When added to the RTP timestamp of the packet, it represents the
92 // "effective" RTP transmission time of the packet, on the RTP
93 // timescale.
94 //
95 // The form of the transmission offset extension block:
96 //
97 //    0                   1                   2                   3
98 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
99 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 //   |  ID   | len=2 |              transmission offset              |
101 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102 constexpr RTPExtensionType TransmissionOffset::kId;
103 constexpr uint8_t TransmissionOffset::kValueSizeBytes;
104 constexpr const char TransmissionOffset::kUri[];
105 
Parse(rtc::ArrayView<const uint8_t> data,int32_t * rtp_time)106 bool TransmissionOffset::Parse(rtc::ArrayView<const uint8_t> data,
107                                int32_t* rtp_time) {
108   if (data.size() != 3)
109     return false;
110   *rtp_time = ByteReader<int32_t, 3>::ReadBigEndian(data.data());
111   return true;
112 }
113 
Write(uint8_t * data,int32_t rtp_time)114 bool TransmissionOffset::Write(uint8_t* data, int32_t rtp_time) {
115   RTC_DCHECK_LE(rtp_time, 0x00ffffff);
116   ByteWriter<int32_t, 3>::WriteBigEndian(data, rtp_time);
117   return true;
118 }
119 
120 //   0                   1                   2
121 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
122 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123 //  |  ID   | L=1   |transport wide sequence number |
124 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125 constexpr RTPExtensionType TransportSequenceNumber::kId;
126 constexpr uint8_t TransportSequenceNumber::kValueSizeBytes;
127 constexpr const char TransportSequenceNumber::kUri[];
128 
Parse(rtc::ArrayView<const uint8_t> data,uint16_t * value)129 bool TransportSequenceNumber::Parse(rtc::ArrayView<const uint8_t> data,
130                                     uint16_t* value) {
131   if (data.size() != 2)
132     return false;
133   *value = ByteReader<uint16_t>::ReadBigEndian(data.data());
134   return true;
135 }
136 
Write(uint8_t * data,uint16_t value)137 bool TransportSequenceNumber::Write(uint8_t* data, uint16_t value) {
138   ByteWriter<uint16_t>::WriteBigEndian(data, value);
139   return true;
140 }
141 
142 // Coordination of Video Orientation in RTP streams.
143 //
144 // Coordination of Video Orientation consists in signaling of the current
145 // orientation of the image captured on the sender side to the receiver for
146 // appropriate rendering and displaying.
147 //
148 //    0                   1
149 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
150 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151 //   |  ID   | len=0 |0 0 0 0 C F R R|
152 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153 constexpr RTPExtensionType VideoOrientation::kId;
154 constexpr uint8_t VideoOrientation::kValueSizeBytes;
155 constexpr const char VideoOrientation::kUri[];
156 
Parse(rtc::ArrayView<const uint8_t> data,VideoRotation * rotation)157 bool VideoOrientation::Parse(rtc::ArrayView<const uint8_t> data,
158                              VideoRotation* rotation) {
159   if (data.size() != 1)
160     return false;
161   *rotation = ConvertCVOByteToVideoRotation(data[0]);
162   return true;
163 }
164 
Write(uint8_t * data,VideoRotation rotation)165 bool VideoOrientation::Write(uint8_t* data, VideoRotation rotation) {
166   data[0] = ConvertVideoRotationToCVOByte(rotation);
167   return true;
168 }
169 
Parse(rtc::ArrayView<const uint8_t> data,uint8_t * value)170 bool VideoOrientation::Parse(rtc::ArrayView<const uint8_t> data,
171                              uint8_t* value) {
172   if (data.size() != 1)
173     return false;
174   *value = data[0];
175   return true;
176 }
177 
Write(uint8_t * data,uint8_t value)178 bool VideoOrientation::Write(uint8_t* data, uint8_t value) {
179   data[0] = value;
180   return true;
181 }
182 
183 //   0                   1                   2                   3
184 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
185 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
186 //  |  ID   | len=2 |   MIN delay           |   MAX delay           |
187 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
188 constexpr RTPExtensionType PlayoutDelayLimits::kId;
189 constexpr uint8_t PlayoutDelayLimits::kValueSizeBytes;
190 constexpr const char PlayoutDelayLimits::kUri[];
191 
Parse(rtc::ArrayView<const uint8_t> data,PlayoutDelay * playout_delay)192 bool PlayoutDelayLimits::Parse(rtc::ArrayView<const uint8_t> data,
193                                PlayoutDelay* playout_delay) {
194   RTC_DCHECK(playout_delay);
195   if (data.size() != 3)
196     return false;
197   uint32_t raw = ByteReader<uint32_t, 3>::ReadBigEndian(data.data());
198   uint16_t min_raw = (raw >> 12);
199   uint16_t max_raw = (raw & 0xfff);
200   if (min_raw > max_raw)
201     return false;
202   playout_delay->min_ms = min_raw * kGranularityMs;
203   playout_delay->max_ms = max_raw * kGranularityMs;
204   return true;
205 }
206 
Write(uint8_t * data,const PlayoutDelay & playout_delay)207 bool PlayoutDelayLimits::Write(uint8_t* data,
208                                const PlayoutDelay& playout_delay) {
209   RTC_DCHECK_LE(0, playout_delay.min_ms);
210   RTC_DCHECK_LE(playout_delay.min_ms, playout_delay.max_ms);
211   RTC_DCHECK_LE(playout_delay.max_ms, kMaxMs);
212   // Convert MS to value to be sent on extension header.
213   uint32_t min_delay = playout_delay.min_ms / kGranularityMs;
214   uint32_t max_delay = playout_delay.max_ms / kGranularityMs;
215   ByteWriter<uint32_t, 3>::WriteBigEndian(data, (min_delay << 12) | max_delay);
216   return true;
217 }
218 
219 // CSRCAudioLevel
220 //  Sample Audio Level Encoding Using the One-Byte Header Format
221 //  Note that the range of len is 1 to 15 which is encoded as 0 to 14
222 //  0                   1                   2                   3
223 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
224 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
225 // |  ID   | len=2 |0|   level 1   |0|   level 2   |0|   level 3   |
226 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
227 
228 
229 constexpr RTPExtensionType CsrcAudioLevel::kId;
230 constexpr const char* CsrcAudioLevel::kUri;
231 
Parse(rtc::ArrayView<const uint8_t> data,CsrcAudioLevelList * csrcAudioLevels)232 bool CsrcAudioLevel::Parse(rtc::ArrayView<const uint8_t> data,
233                            CsrcAudioLevelList* csrcAudioLevels) {
234   if (data.size() < 1 || data.size() > kRtpCsrcSize)
235     return false;
236   csrcAudioLevels->numAudioLevels = data.size();
237   for(uint8_t i = 0; i < csrcAudioLevels->numAudioLevels; i++) {
238     // Ensure range is 0 to 127 inclusive
239     csrcAudioLevels->arrOfAudioLevels[i] = 0x7f & data[i];
240   }
241   return true;
242 }
243 
ValueSize(const CsrcAudioLevelList & csrcAudioLevels)244 size_t CsrcAudioLevel::ValueSize(const CsrcAudioLevelList& csrcAudioLevels) {
245   return csrcAudioLevels.numAudioLevels;
246 }
247 
Write(uint8_t * data,const CsrcAudioLevelList & csrcAudioLevels)248 bool CsrcAudioLevel::Write(uint8_t* data,
249                            const CsrcAudioLevelList& csrcAudioLevels) {
250   RTC_DCHECK_GE(csrcAudioLevels.numAudioLevels, 0);
251   for(uint8_t i = 0; i < csrcAudioLevels.numAudioLevels; i++) {
252     data[i] = csrcAudioLevels.arrOfAudioLevels[i] & 0x7f;
253   }
254   // This extension if used must have at least one audio level
255   return csrcAudioLevels.numAudioLevels;
256 }
257 
258 // Video Content Type.
259 //
260 // E.g. default video or screenshare.
261 //
262 //    0                   1
263 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
264 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265 //   |  ID   | len=0 | Content type  |
266 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
267 constexpr RTPExtensionType VideoContentTypeExtension::kId;
268 constexpr uint8_t VideoContentTypeExtension::kValueSizeBytes;
269 constexpr const char VideoContentTypeExtension::kUri[];
270 
Parse(rtc::ArrayView<const uint8_t> data,VideoContentType * content_type)271 bool VideoContentTypeExtension::Parse(rtc::ArrayView<const uint8_t> data,
272                                       VideoContentType* content_type) {
273   if (data.size() == 1 &&
274       videocontenttypehelpers::IsValidContentType(data[0])) {
275     *content_type = static_cast<VideoContentType>(data[0]);
276     return true;
277   }
278   return false;
279 }
280 
Write(uint8_t * data,VideoContentType content_type)281 bool VideoContentTypeExtension::Write(uint8_t* data,
282                                       VideoContentType content_type) {
283   data[0] = static_cast<uint8_t>(content_type);
284   return true;
285 }
286 
287 // Video Timing.
288 // 6 timestamps in milliseconds counted from capture time stored in rtp header:
289 // encode start/finish, packetization complete, pacer exit and reserved for
290 // modification by the network modification. |flags| is a bitmask and has the
291 // following allowed values:
292 // 0 = Valid data, but no flags available (backwards compatibility)
293 // 1 = Frame marked as timing frame due to cyclic timer.
294 // 2 = Frame marked as timing frame due to size being outside limit.
295 // 255 = Invalid. The whole timing frame extension should be ignored.
296 //
297 //    0                   1                   2                   3
298 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
299 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
300 //   |  ID   | len=12|     flags     |     encode start ms delta       |
301 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
302 //   |    encode finish ms delta     |   packetizer finish ms delta    |
303 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
304 //   |     pacer exit ms delta       |   network timestamp ms delta    |
305 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
306 //   |  network2 timestamp ms delta  |
307 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
308 
309 constexpr RTPExtensionType VideoTimingExtension::kId;
310 constexpr uint8_t VideoTimingExtension::kValueSizeBytes;
311 constexpr const char VideoTimingExtension::kUri[];
312 
Parse(rtc::ArrayView<const uint8_t> data,VideoSendTiming * timing)313 bool VideoTimingExtension::Parse(rtc::ArrayView<const uint8_t> data,
314                                  VideoSendTiming* timing) {
315   RTC_DCHECK(timing);
316   // TODO(sprang): Deprecate support for old wire format.
317   ptrdiff_t off = 0;
318   switch (data.size()) {
319     case kValueSizeBytes - 1:
320       timing->flags = 0;
321       off = 1;  // Old wire format without the flags field.
322       break;
323     case kValueSizeBytes:
324       timing->flags = ByteReader<uint8_t>::ReadBigEndian(data.data());
325       break;
326     default:
327       return false;
328   }
329 
330   timing->encode_start_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
331       data.data() + VideoSendTiming::kEncodeStartDeltaOffset - off);
332   timing->encode_finish_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
333       data.data() + VideoSendTiming::kEncodeFinishDeltaOffset - off);
334   timing->packetization_finish_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
335       data.data() + VideoSendTiming::kPacketizationFinishDeltaOffset - off);
336   timing->pacer_exit_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
337       data.data() + VideoSendTiming::kPacerExitDeltaOffset - off);
338   timing->network_timestamp_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
339       data.data() + VideoSendTiming::kNetworkTimestampDeltaOffset - off);
340   timing->network2_timestamp_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
341       data.data() + VideoSendTiming::kNetwork2TimestampDeltaOffset - off);
342   return true;
343 }
344 
Write(uint8_t * data,const VideoSendTiming & timing)345 bool VideoTimingExtension::Write(uint8_t* data, const VideoSendTiming& timing) {
346   ByteWriter<uint8_t>::WriteBigEndian(data + VideoSendTiming::kFlagsOffset,
347                                       timing.flags);
348   ByteWriter<uint16_t>::WriteBigEndian(
349       data + VideoSendTiming::kEncodeStartDeltaOffset,
350       timing.encode_start_delta_ms);
351   ByteWriter<uint16_t>::WriteBigEndian(
352       data + VideoSendTiming::kEncodeFinishDeltaOffset,
353       timing.encode_finish_delta_ms);
354   ByteWriter<uint16_t>::WriteBigEndian(
355       data + VideoSendTiming::kPacketizationFinishDeltaOffset,
356       timing.packetization_finish_delta_ms);
357   ByteWriter<uint16_t>::WriteBigEndian(
358       data + VideoSendTiming::kPacerExitDeltaOffset,
359       timing.pacer_exit_delta_ms);
360   ByteWriter<uint16_t>::WriteBigEndian(
361       data + VideoSendTiming::kNetworkTimestampDeltaOffset,
362       timing.network_timestamp_delta_ms);
363   ByteWriter<uint16_t>::WriteBigEndian(
364       data + VideoSendTiming::kNetwork2TimestampDeltaOffset,
365       timing.network2_timestamp_delta_ms);
366   return true;
367 }
368 
Write(uint8_t * data,uint16_t time_delta_ms,uint8_t offset)369 bool VideoTimingExtension::Write(uint8_t* data,
370                                  uint16_t time_delta_ms,
371                                  uint8_t offset) {
372   RTC_DCHECK_LE(offset, kValueSizeBytes - sizeof(uint16_t));
373   ByteWriter<uint16_t>::WriteBigEndian(data + offset, time_delta_ms);
374   return true;
375 }
376 
Parse(rtc::ArrayView<const uint8_t> data,StringRtpHeaderExtension * str)377 bool BaseRtpStringExtension::Parse(rtc::ArrayView<const uint8_t> data,
378                                    StringRtpHeaderExtension* str) {
379   if (data.empty() || data[0] == 0)  // Valid string extension can't be empty.
380     return false;
381   str->Set(data);
382   RTC_DCHECK(!str->empty());
383   return true;
384 }
385 
Write(uint8_t * data,const StringRtpHeaderExtension & str)386 bool BaseRtpStringExtension::Write(uint8_t* data,
387                                    const StringRtpHeaderExtension& str) {
388   RTC_DCHECK_GE(str.size(), 1);
389   RTC_DCHECK_LE(str.size(), StringRtpHeaderExtension::kMaxSize);
390   memcpy(data, str.data(), str.size());
391   return true;
392 }
393 
Parse(rtc::ArrayView<const uint8_t> data,std::string * str)394 bool BaseRtpStringExtension::Parse(rtc::ArrayView<const uint8_t> data,
395                                    std::string* str) {
396   if (data.empty() || data[0] == 0)  // Valid string extension can't be empty.
397     return false;
398   const char* cstr = reinterpret_cast<const char*>(data.data());
399   // If there is a \0 character in the middle of the |data|, treat it as end
400   // of the string. Well-formed string extensions shouldn't contain it.
401   str->assign(cstr, strnlen(cstr, data.size()));
402   RTC_DCHECK(!str->empty());
403   return true;
404 }
405 
Write(uint8_t * data,const std::string & str)406 bool BaseRtpStringExtension::Write(uint8_t* data, const std::string& str) {
407   RTC_DCHECK_GE(str.size(), 1);
408   RTC_DCHECK_LE(str.size(), StringRtpHeaderExtension::kMaxSize);
409   memcpy(data, str.data(), str.size());
410   return true;
411 }
412 
413 // Constant declarations for string RTP header extension types.
414 
415 constexpr RTPExtensionType RtpStreamId::kId;
416 constexpr const char RtpStreamId::kUri[];
417 
418 constexpr RTPExtensionType RepairedRtpStreamId::kId;
419 constexpr const char RepairedRtpStreamId::kUri[];
420 
421 constexpr RTPExtensionType RtpMid::kId;
422 constexpr const char RtpMid::kUri[];
423 
424 }  // namespace webrtc
425