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 <string.h>
14 
15 #include <cmath>
16 #include <limits>
17 
18 #include "modules/rtp_rtcp/include/rtp_cvo.h"
19 #include "modules/rtp_rtcp/source/byte_io.h"
20 // TODO(bug:9855) Move kNoSpatialIdx from vp9_globals.h to common_constants
21 #include "modules/video_coding/codecs/interface/common_constants.h"
22 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
23 #include "rtc_base/checks.h"
24 
25 namespace webrtc {
26 // Absolute send time in RTP streams.
27 //
28 // The absolute send time is signaled to the receiver in-band using the
29 // general mechanism for RTP header extensions [RFC8285]. The payload
30 // of this extension (the transmitted value) is a 24-bit unsigned integer
31 // containing the sender's current time in seconds as a fixed point number
32 // with 18 bits fractional part.
33 //
34 // The form of the absolute send time extension block:
35 //
36 //    0                   1                   2                   3
37 //    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
38 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 //   |  ID   | len=2 |              absolute send time               |
40 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 constexpr RTPExtensionType AbsoluteSendTime::kId;
42 constexpr uint8_t AbsoluteSendTime::kValueSizeBytes;
43 constexpr const char AbsoluteSendTime::kUri[];
44 
Parse(rtc::ArrayView<const uint8_t> data,uint32_t * time_24bits)45 bool AbsoluteSendTime::Parse(rtc::ArrayView<const uint8_t> data,
46                              uint32_t* time_24bits) {
47   if (data.size() != 3)
48     return false;
49   *time_24bits = ByteReader<uint32_t, 3>::ReadBigEndian(data.data());
50   return true;
51 }
52 
Write(rtc::ArrayView<uint8_t> data,uint32_t time_24bits)53 bool AbsoluteSendTime::Write(rtc::ArrayView<uint8_t> data,
54                              uint32_t time_24bits) {
55   RTC_DCHECK_EQ(data.size(), 3);
56   RTC_DCHECK_LE(time_24bits, 0x00FFFFFF);
57   ByteWriter<uint32_t, 3>::WriteBigEndian(data.data(), time_24bits);
58   return true;
59 }
60 
61 // Absolute Capture Time
62 //
63 // The Absolute Capture Time extension is used to stamp RTP packets with a NTP
64 // timestamp showing when the first audio or video frame in a packet was
65 // originally captured. The intent of this extension is to provide a way to
66 // accomplish audio-to-video synchronization when RTCP-terminating intermediate
67 // systems (e.g. mixers) are involved.
68 //
69 // Data layout of the shortened version of abs-capture-time:
70 //
71 //    0                   1                   2                   3
72 //    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
73 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74 //   |  ID   | len=7 |     absolute capture timestamp (bit 0-23)     |
75 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76 //   |             absolute capture timestamp (bit 24-55)            |
77 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78 //   |  ... (56-63)  |
79 //   +-+-+-+-+-+-+-+-+
80 //
81 // Data layout of the extended version of abs-capture-time:
82 //
83 //    0                   1                   2                   3
84 //    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
85 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
86 //   |  ID   | len=15|     absolute capture timestamp (bit 0-23)     |
87 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88 //   |             absolute capture timestamp (bit 24-55)            |
89 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 //   |  ... (56-63)  |   estimated capture clock offset (bit 0-23)   |
91 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92 //   |           estimated capture clock offset (bit 24-55)          |
93 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 //   |  ... (56-63)  |
95 //   +-+-+-+-+-+-+-+-+
96 constexpr RTPExtensionType AbsoluteCaptureTimeExtension::kId;
97 constexpr uint8_t AbsoluteCaptureTimeExtension::kValueSizeBytes;
98 constexpr uint8_t AbsoluteCaptureTimeExtension::
99     kValueSizeBytesWithoutEstimatedCaptureClockOffset;
100 constexpr const char AbsoluteCaptureTimeExtension::kUri[];
101 
Parse(rtc::ArrayView<const uint8_t> data,AbsoluteCaptureTime * extension)102 bool AbsoluteCaptureTimeExtension::Parse(rtc::ArrayView<const uint8_t> data,
103                                          AbsoluteCaptureTime* extension) {
104   if (data.size() != kValueSizeBytes &&
105       data.size() != kValueSizeBytesWithoutEstimatedCaptureClockOffset) {
106     return false;
107   }
108 
109   extension->absolute_capture_timestamp =
110       ByteReader<uint64_t>::ReadBigEndian(data.data());
111 
112   if (data.size() != kValueSizeBytesWithoutEstimatedCaptureClockOffset) {
113     extension->estimated_capture_clock_offset =
114         ByteReader<int64_t>::ReadBigEndian(data.data() + 8);
115   }
116 
117   return true;
118 }
119 
ValueSize(const AbsoluteCaptureTime & extension)120 size_t AbsoluteCaptureTimeExtension::ValueSize(
121     const AbsoluteCaptureTime& extension) {
122   if (extension.estimated_capture_clock_offset != absl::nullopt) {
123     return kValueSizeBytes;
124   } else {
125     return kValueSizeBytesWithoutEstimatedCaptureClockOffset;
126   }
127 }
128 
Write(rtc::ArrayView<uint8_t> data,const AbsoluteCaptureTime & extension)129 bool AbsoluteCaptureTimeExtension::Write(rtc::ArrayView<uint8_t> data,
130                                          const AbsoluteCaptureTime& extension) {
131   RTC_DCHECK_EQ(data.size(), ValueSize(extension));
132 
133   ByteWriter<uint64_t>::WriteBigEndian(data.data(),
134                                        extension.absolute_capture_timestamp);
135 
136   if (data.size() != kValueSizeBytesWithoutEstimatedCaptureClockOffset) {
137     ByteWriter<int64_t>::WriteBigEndian(
138         data.data() + 8, extension.estimated_capture_clock_offset.value());
139   }
140 
141   return true;
142 }
143 
144 // An RTP Header Extension for Client-to-Mixer Audio Level Indication
145 //
146 // https://tools.ietf.org/html/rfc6464
147 //
148 // The form of the audio level extension block:
149 //
150 //  0                   1
151 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
152 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
153 // |  ID   | len=0 |V| level       |
154 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 // Sample Audio Level Encoding Using the One-Byte Header Format
156 //
157 //  0                   1                   2
158 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
159 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 // |      ID       |     len=1     |V|    level    |
161 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162 // Sample Audio Level Encoding Using the Two-Byte Header Format
163 
164 constexpr RTPExtensionType AudioLevel::kId;
165 constexpr uint8_t AudioLevel::kValueSizeBytes;
166 constexpr const char AudioLevel::kUri[];
167 
Parse(rtc::ArrayView<const uint8_t> data,bool * voice_activity,uint8_t * audio_level)168 bool AudioLevel::Parse(rtc::ArrayView<const uint8_t> data,
169                        bool* voice_activity,
170                        uint8_t* audio_level) {
171   // One-byte and two-byte format share the same data definition.
172   if (data.size() != 1)
173     return false;
174   *voice_activity = (data[0] & 0x80) != 0;
175   *audio_level = data[0] & 0x7F;
176   return true;
177 }
178 
Write(rtc::ArrayView<uint8_t> data,bool voice_activity,uint8_t audio_level)179 bool AudioLevel::Write(rtc::ArrayView<uint8_t> data,
180                        bool voice_activity,
181                        uint8_t audio_level) {
182   // One-byte and two-byte format share the same data definition.
183   RTC_DCHECK_EQ(data.size(), 1);
184   RTC_CHECK_LE(audio_level, 0x7f);
185   data[0] = (voice_activity ? 0x80 : 0x00) | audio_level;
186   return true;
187 }
188 
189 // From RFC 5450: Transmission Time Offsets in RTP Streams.
190 //
191 // The transmission time is signaled to the receiver in-band using the
192 // general mechanism for RTP header extensions [RFC8285]. The payload
193 // of this extension (the transmitted value) is a 24-bit signed integer.
194 // When added to the RTP timestamp of the packet, it represents the
195 // "effective" RTP transmission time of the packet, on the RTP
196 // timescale.
197 //
198 // The form of the transmission offset extension block:
199 //
200 //    0                   1                   2                   3
201 //    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
202 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
203 //   |  ID   | len=2 |              transmission offset              |
204 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
205 constexpr RTPExtensionType TransmissionOffset::kId;
206 constexpr uint8_t TransmissionOffset::kValueSizeBytes;
207 constexpr const char TransmissionOffset::kUri[];
208 
Parse(rtc::ArrayView<const uint8_t> data,int32_t * rtp_time)209 bool TransmissionOffset::Parse(rtc::ArrayView<const uint8_t> data,
210                                int32_t* rtp_time) {
211   if (data.size() != 3)
212     return false;
213   *rtp_time = ByteReader<int32_t, 3>::ReadBigEndian(data.data());
214   return true;
215 }
216 
Write(rtc::ArrayView<uint8_t> data,int32_t rtp_time)217 bool TransmissionOffset::Write(rtc::ArrayView<uint8_t> data, int32_t rtp_time) {
218   RTC_DCHECK_EQ(data.size(), 3);
219   RTC_DCHECK_LE(rtp_time, 0x00ffffff);
220   ByteWriter<int32_t, 3>::WriteBigEndian(data.data(), rtp_time);
221   return true;
222 }
223 
224 // TransportSequenceNumber
225 //
226 //   0                   1                   2
227 //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
228 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
229 //  |  ID   | L=1   |transport-wide sequence number |
230 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
231 constexpr RTPExtensionType TransportSequenceNumber::kId;
232 constexpr uint8_t TransportSequenceNumber::kValueSizeBytes;
233 constexpr const char TransportSequenceNumber::kUri[];
234 
Parse(rtc::ArrayView<const uint8_t> data,uint16_t * transport_sequence_number)235 bool TransportSequenceNumber::Parse(rtc::ArrayView<const uint8_t> data,
236                                     uint16_t* transport_sequence_number) {
237   if (data.size() != kValueSizeBytes)
238     return false;
239   *transport_sequence_number = ByteReader<uint16_t>::ReadBigEndian(data.data());
240   return true;
241 }
242 
Write(rtc::ArrayView<uint8_t> data,uint16_t transport_sequence_number)243 bool TransportSequenceNumber::Write(rtc::ArrayView<uint8_t> data,
244                                     uint16_t transport_sequence_number) {
245   RTC_DCHECK_EQ(data.size(), ValueSize(transport_sequence_number));
246   ByteWriter<uint16_t>::WriteBigEndian(data.data(), transport_sequence_number);
247   return true;
248 }
249 
250 // TransportSequenceNumberV2
251 //
252 // In addition to the format used for TransportSequencNumber, V2 also supports
253 // the following packet format where two extra bytes are used to specify that
254 // the sender requests immediate feedback.
255 //   0                   1                   2                   3
256 //   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
257 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
258 //  |  ID   | L=3   |transport-wide sequence number |T|  seq count  |
259 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
260 //  |seq count cont.|
261 //  +-+-+-+-+-+-+-+-+
262 //
263 // The bit |T| determines whether the feedback should include timing information
264 // or not and |seq_count| determines how many packets the feedback packet should
265 // cover including the current packet. If |seq_count| is zero no feedback is
266 // requested.
267 constexpr RTPExtensionType TransportSequenceNumberV2::kId;
268 constexpr uint8_t TransportSequenceNumberV2::kValueSizeBytes;
269 constexpr uint8_t
270     TransportSequenceNumberV2::kValueSizeBytesWithoutFeedbackRequest;
271 constexpr const char TransportSequenceNumberV2::kUri[];
272 constexpr uint16_t TransportSequenceNumberV2::kIncludeTimestampsBit;
273 
Parse(rtc::ArrayView<const uint8_t> data,uint16_t * transport_sequence_number,absl::optional<FeedbackRequest> * feedback_request)274 bool TransportSequenceNumberV2::Parse(
275     rtc::ArrayView<const uint8_t> data,
276     uint16_t* transport_sequence_number,
277     absl::optional<FeedbackRequest>* feedback_request) {
278   if (data.size() != kValueSizeBytes &&
279       data.size() != kValueSizeBytesWithoutFeedbackRequest)
280     return false;
281 
282   *transport_sequence_number = ByteReader<uint16_t>::ReadBigEndian(data.data());
283 
284   *feedback_request = absl::nullopt;
285   if (data.size() == kValueSizeBytes) {
286     uint16_t feedback_request_raw =
287         ByteReader<uint16_t>::ReadBigEndian(data.data() + 2);
288     bool include_timestamps =
289         (feedback_request_raw & kIncludeTimestampsBit) != 0;
290     uint16_t sequence_count = feedback_request_raw & ~kIncludeTimestampsBit;
291 
292     // If |sequence_count| is zero no feedback is requested.
293     if (sequence_count != 0) {
294       *feedback_request = {include_timestamps, sequence_count};
295     }
296   }
297   return true;
298 }
299 
Write(rtc::ArrayView<uint8_t> data,uint16_t transport_sequence_number,const absl::optional<FeedbackRequest> & feedback_request)300 bool TransportSequenceNumberV2::Write(
301     rtc::ArrayView<uint8_t> data,
302     uint16_t transport_sequence_number,
303     const absl::optional<FeedbackRequest>& feedback_request) {
304   RTC_DCHECK_EQ(data.size(),
305                 ValueSize(transport_sequence_number, feedback_request));
306 
307   ByteWriter<uint16_t>::WriteBigEndian(data.data(), transport_sequence_number);
308 
309   if (feedback_request) {
310     RTC_DCHECK_GE(feedback_request->sequence_count, 0);
311     RTC_DCHECK_LT(feedback_request->sequence_count, kIncludeTimestampsBit);
312     uint16_t feedback_request_raw =
313         feedback_request->sequence_count |
314         (feedback_request->include_timestamps ? kIncludeTimestampsBit : 0);
315     ByteWriter<uint16_t>::WriteBigEndian(data.data() + 2, feedback_request_raw);
316   }
317   return true;
318 }
319 
320 // Coordination of Video Orientation in RTP streams.
321 //
322 // Coordination of Video Orientation consists in signaling of the current
323 // orientation of the image captured on the sender side to the receiver for
324 // appropriate rendering and displaying.
325 //
326 //    0                   1
327 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
328 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
329 //   |  ID   | len=0 |0 0 0 0 C F R R|
330 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
331 constexpr RTPExtensionType VideoOrientation::kId;
332 constexpr uint8_t VideoOrientation::kValueSizeBytes;
333 constexpr const char VideoOrientation::kUri[];
334 
Parse(rtc::ArrayView<const uint8_t> data,VideoRotation * rotation)335 bool VideoOrientation::Parse(rtc::ArrayView<const uint8_t> data,
336                              VideoRotation* rotation) {
337   if (data.size() != 1)
338     return false;
339   *rotation = ConvertCVOByteToVideoRotation(data[0]);
340   return true;
341 }
342 
Write(rtc::ArrayView<uint8_t> data,VideoRotation rotation)343 bool VideoOrientation::Write(rtc::ArrayView<uint8_t> data,
344                              VideoRotation rotation) {
345   RTC_DCHECK_EQ(data.size(), 1);
346   data[0] = ConvertVideoRotationToCVOByte(rotation);
347   return true;
348 }
349 
Parse(rtc::ArrayView<const uint8_t> data,uint8_t * value)350 bool VideoOrientation::Parse(rtc::ArrayView<const uint8_t> data,
351                              uint8_t* value) {
352   if (data.size() != 1)
353     return false;
354   *value = data[0];
355   return true;
356 }
357 
Write(rtc::ArrayView<uint8_t> data,uint8_t value)358 bool VideoOrientation::Write(rtc::ArrayView<uint8_t> data, uint8_t value) {
359   RTC_DCHECK_EQ(data.size(), 1);
360   data[0] = value;
361   return true;
362 }
363 
364 //   0                   1                   2                   3
365 //   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
366 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367 //  |  ID   | len=2 |   MIN delay           |   MAX delay           |
368 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
369 constexpr RTPExtensionType PlayoutDelayLimits::kId;
370 constexpr uint8_t PlayoutDelayLimits::kValueSizeBytes;
371 constexpr const char PlayoutDelayLimits::kUri[];
372 
Parse(rtc::ArrayView<const uint8_t> data,PlayoutDelay * playout_delay)373 bool PlayoutDelayLimits::Parse(rtc::ArrayView<const uint8_t> data,
374                                PlayoutDelay* playout_delay) {
375   RTC_DCHECK(playout_delay);
376   if (data.size() != 3)
377     return false;
378   uint32_t raw = ByteReader<uint32_t, 3>::ReadBigEndian(data.data());
379   uint16_t min_raw = (raw >> 12);
380   uint16_t max_raw = (raw & 0xfff);
381   if (min_raw > max_raw)
382     return false;
383   playout_delay->min_ms = min_raw * kGranularityMs;
384   playout_delay->max_ms = max_raw * kGranularityMs;
385   return true;
386 }
387 
Write(rtc::ArrayView<uint8_t> data,const PlayoutDelay & playout_delay)388 bool PlayoutDelayLimits::Write(rtc::ArrayView<uint8_t> data,
389                                const PlayoutDelay& playout_delay) {
390   RTC_DCHECK_EQ(data.size(), 3);
391   RTC_DCHECK_LE(0, playout_delay.min_ms);
392   RTC_DCHECK_LE(playout_delay.min_ms, playout_delay.max_ms);
393   RTC_DCHECK_LE(playout_delay.max_ms, kMaxMs);
394   // Convert MS to value to be sent on extension header.
395   uint32_t min_delay = playout_delay.min_ms / kGranularityMs;
396   uint32_t max_delay = playout_delay.max_ms / kGranularityMs;
397   ByteWriter<uint32_t, 3>::WriteBigEndian(data.data(),
398                                           (min_delay << 12) | max_delay);
399   return true;
400 }
401 
402 // Video Content Type.
403 //
404 // E.g. default video or screenshare.
405 //
406 //    0                   1
407 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
408 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
409 //   |  ID   | len=0 | Content type  |
410 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
411 constexpr RTPExtensionType VideoContentTypeExtension::kId;
412 constexpr uint8_t VideoContentTypeExtension::kValueSizeBytes;
413 constexpr const char VideoContentTypeExtension::kUri[];
414 
Parse(rtc::ArrayView<const uint8_t> data,VideoContentType * content_type)415 bool VideoContentTypeExtension::Parse(rtc::ArrayView<const uint8_t> data,
416                                       VideoContentType* content_type) {
417   if (data.size() == 1 &&
418       videocontenttypehelpers::IsValidContentType(data[0])) {
419     *content_type = static_cast<VideoContentType>(data[0]);
420     return true;
421   }
422   return false;
423 }
424 
Write(rtc::ArrayView<uint8_t> data,VideoContentType content_type)425 bool VideoContentTypeExtension::Write(rtc::ArrayView<uint8_t> data,
426                                       VideoContentType content_type) {
427   RTC_DCHECK_EQ(data.size(), 1);
428   data[0] = static_cast<uint8_t>(content_type);
429   return true;
430 }
431 
432 // Video Timing.
433 // 6 timestamps in milliseconds counted from capture time stored in rtp header:
434 // encode start/finish, packetization complete, pacer exit and reserved for
435 // modification by the network modification. |flags| is a bitmask and has the
436 // following allowed values:
437 // 0 = Valid data, but no flags available (backwards compatibility)
438 // 1 = Frame marked as timing frame due to cyclic timer.
439 // 2 = Frame marked as timing frame due to size being outside limit.
440 // 255 = Invalid. The whole timing frame extension should be ignored.
441 //
442 //    0                   1                   2                   3
443 //    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
444 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
445 //   |  ID   | len=12|     flags     |     encode start ms delta     |
446 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
447 //   |    encode finish ms delta     |  packetizer finish ms delta   |
448 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
449 //   |     pacer exit ms delta       |  network timestamp ms delta   |
450 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
451 //   |  network2 timestamp ms delta  |
452 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
453 
454 constexpr RTPExtensionType VideoTimingExtension::kId;
455 constexpr uint8_t VideoTimingExtension::kValueSizeBytes;
456 constexpr const char VideoTimingExtension::kUri[];
457 constexpr uint8_t VideoTimingExtension::kFlagsOffset;
458 constexpr uint8_t VideoTimingExtension::kEncodeStartDeltaOffset;
459 constexpr uint8_t VideoTimingExtension::kEncodeFinishDeltaOffset;
460 constexpr uint8_t VideoTimingExtension::kPacketizationFinishDeltaOffset;
461 constexpr uint8_t VideoTimingExtension::kPacerExitDeltaOffset;
462 constexpr uint8_t VideoTimingExtension::kNetworkTimestampDeltaOffset;
463 constexpr uint8_t VideoTimingExtension::kNetwork2TimestampDeltaOffset;
464 
Parse(rtc::ArrayView<const uint8_t> data,VideoSendTiming * timing)465 bool VideoTimingExtension::Parse(rtc::ArrayView<const uint8_t> data,
466                                  VideoSendTiming* timing) {
467   RTC_DCHECK(timing);
468   // TODO(sprang): Deprecate support for old wire format.
469   ptrdiff_t off = 0;
470   switch (data.size()) {
471     case kValueSizeBytes - 1:
472       timing->flags = 0;
473       off = 1;  // Old wire format without the flags field.
474       break;
475     case kValueSizeBytes:
476       timing->flags = ByteReader<uint8_t>::ReadBigEndian(data.data());
477       break;
478     default:
479       return false;
480   }
481 
482   timing->encode_start_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
483       data.data() + kEncodeStartDeltaOffset - off);
484   timing->encode_finish_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
485       data.data() + kEncodeFinishDeltaOffset - off);
486   timing->packetization_finish_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
487       data.data() + kPacketizationFinishDeltaOffset - off);
488   timing->pacer_exit_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
489       data.data() + kPacerExitDeltaOffset - off);
490   timing->network_timestamp_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
491       data.data() + kNetworkTimestampDeltaOffset - off);
492   timing->network2_timestamp_delta_ms = ByteReader<uint16_t>::ReadBigEndian(
493       data.data() + kNetwork2TimestampDeltaOffset - off);
494   return true;
495 }
496 
Write(rtc::ArrayView<uint8_t> data,const VideoSendTiming & timing)497 bool VideoTimingExtension::Write(rtc::ArrayView<uint8_t> data,
498                                  const VideoSendTiming& timing) {
499   RTC_DCHECK_EQ(data.size(), 1 + 2 * 6);
500   ByteWriter<uint8_t>::WriteBigEndian(data.data() + kFlagsOffset, timing.flags);
501   ByteWriter<uint16_t>::WriteBigEndian(data.data() + kEncodeStartDeltaOffset,
502                                        timing.encode_start_delta_ms);
503   ByteWriter<uint16_t>::WriteBigEndian(data.data() + kEncodeFinishDeltaOffset,
504                                        timing.encode_finish_delta_ms);
505   ByteWriter<uint16_t>::WriteBigEndian(
506       data.data() + kPacketizationFinishDeltaOffset,
507       timing.packetization_finish_delta_ms);
508   ByteWriter<uint16_t>::WriteBigEndian(data.data() + kPacerExitDeltaOffset,
509                                        timing.pacer_exit_delta_ms);
510   ByteWriter<uint16_t>::WriteBigEndian(
511       data.data() + kNetworkTimestampDeltaOffset,
512       timing.network_timestamp_delta_ms);
513   ByteWriter<uint16_t>::WriteBigEndian(
514       data.data() + kNetwork2TimestampDeltaOffset,
515       timing.network2_timestamp_delta_ms);
516   return true;
517 }
518 
Write(rtc::ArrayView<uint8_t> data,uint16_t time_delta_ms,uint8_t offset)519 bool VideoTimingExtension::Write(rtc::ArrayView<uint8_t> data,
520                                  uint16_t time_delta_ms,
521                                  uint8_t offset) {
522   RTC_DCHECK_GE(data.size(), offset + 2);
523   RTC_DCHECK_LE(offset, kValueSizeBytes - sizeof(uint16_t));
524   ByteWriter<uint16_t>::WriteBigEndian(data.data() + offset, time_delta_ms);
525   return true;
526 }
527 
528 // Color space including HDR metadata as an optional field.
529 //
530 // RTP header extension to carry color space information and optionally HDR
531 // metadata. The float values in the HDR metadata struct are upscaled by a
532 // static factor and transmitted as unsigned integers.
533 //
534 // Data layout of color space with HDR metadata (two-byte RTP header extension)
535 //    0                   1                   2                   3
536 //    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
537 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538 //   |      ID       |   length=28   |   primaries   |   transfer    |
539 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540 //   |    matrix     |range+chr.sit. |         luminance_max         |
541 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542 //   |         luminance_min         |            mastering_metadata.|
543 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
544 //   |primary_r.x and .y             |            mastering_metadata.|
545 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546 //   |primary_g.x and .y             |            mastering_metadata.|
547 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
548 //   |primary_b.x and .y             |            mastering_metadata.|
549 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
550 //   |white.x and .y                 |    max_content_light_level    |
551 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
552 //   | max_frame_average_light_level |
553 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
554 //
555 // Data layout of color space w/o HDR metadata (one-byte RTP header extension)
556 //    0                   1                   2                   3
557 //    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
558 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559 //   |  ID   | L = 3 |   primaries   |   transfer    |    matrix     |
560 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
561 //   |range+chr.sit. |
562 //   +-+-+-+-+-+-+-+-+
563 
564 constexpr RTPExtensionType ColorSpaceExtension::kId;
565 constexpr uint8_t ColorSpaceExtension::kValueSizeBytes;
566 constexpr const char ColorSpaceExtension::kUri[];
567 
Parse(rtc::ArrayView<const uint8_t> data,ColorSpace * color_space)568 bool ColorSpaceExtension::Parse(rtc::ArrayView<const uint8_t> data,
569                                 ColorSpace* color_space) {
570   RTC_DCHECK(color_space);
571   if (data.size() != kValueSizeBytes &&
572       data.size() != kValueSizeBytesWithoutHdrMetadata)
573     return false;
574 
575   size_t offset = 0;
576   // Read color space information.
577   if (!color_space->set_primaries_from_uint8(data[offset++]))
578     return false;
579   if (!color_space->set_transfer_from_uint8(data[offset++]))
580     return false;
581   if (!color_space->set_matrix_from_uint8(data[offset++]))
582     return false;
583 
584   uint8_t range_and_chroma_siting = data[offset++];
585   if (!color_space->set_range_from_uint8((range_and_chroma_siting >> 4) & 0x03))
586     return false;
587   if (!color_space->set_chroma_siting_horizontal_from_uint8(
588           (range_and_chroma_siting >> 2) & 0x03))
589     return false;
590   if (!color_space->set_chroma_siting_vertical_from_uint8(
591           range_and_chroma_siting & 0x03))
592     return false;
593 
594   // Read HDR metadata if it exists, otherwise clear it.
595   if (data.size() == kValueSizeBytesWithoutHdrMetadata) {
596     color_space->set_hdr_metadata(nullptr);
597   } else {
598     HdrMetadata hdr_metadata;
599     offset += ParseHdrMetadata(data.subview(offset), &hdr_metadata);
600     if (!hdr_metadata.Validate())
601       return false;
602     color_space->set_hdr_metadata(&hdr_metadata);
603   }
604   RTC_DCHECK_EQ(ValueSize(*color_space), offset);
605   return true;
606 }
607 
Write(rtc::ArrayView<uint8_t> data,const ColorSpace & color_space)608 bool ColorSpaceExtension::Write(rtc::ArrayView<uint8_t> data,
609                                 const ColorSpace& color_space) {
610   RTC_DCHECK_EQ(data.size(), ValueSize(color_space));
611   size_t offset = 0;
612   // Write color space information.
613   data[offset++] = static_cast<uint8_t>(color_space.primaries());
614   data[offset++] = static_cast<uint8_t>(color_space.transfer());
615   data[offset++] = static_cast<uint8_t>(color_space.matrix());
616   data[offset++] = CombineRangeAndChromaSiting(
617       color_space.range(), color_space.chroma_siting_horizontal(),
618       color_space.chroma_siting_vertical());
619 
620   // Write HDR metadata if it exists.
621   if (color_space.hdr_metadata()) {
622     offset +=
623         WriteHdrMetadata(data.subview(offset), *color_space.hdr_metadata());
624   }
625   RTC_DCHECK_EQ(ValueSize(color_space), offset);
626   return true;
627 }
628 
629 // Combines range and chroma siting into one byte with the following bit layout:
630 // bits 0-1 Chroma siting vertical.
631 //      2-3 Chroma siting horizontal.
632 //      4-5 Range.
633 //      6-7 Unused.
CombineRangeAndChromaSiting(ColorSpace::RangeID range,ColorSpace::ChromaSiting chroma_siting_horizontal,ColorSpace::ChromaSiting chroma_siting_vertical)634 uint8_t ColorSpaceExtension::CombineRangeAndChromaSiting(
635     ColorSpace::RangeID range,
636     ColorSpace::ChromaSiting chroma_siting_horizontal,
637     ColorSpace::ChromaSiting chroma_siting_vertical) {
638   RTC_DCHECK_LE(static_cast<uint8_t>(range), 3);
639   RTC_DCHECK_LE(static_cast<uint8_t>(chroma_siting_horizontal), 3);
640   RTC_DCHECK_LE(static_cast<uint8_t>(chroma_siting_vertical), 3);
641   return (static_cast<uint8_t>(range) << 4) |
642          (static_cast<uint8_t>(chroma_siting_horizontal) << 2) |
643          static_cast<uint8_t>(chroma_siting_vertical);
644 }
645 
ParseHdrMetadata(rtc::ArrayView<const uint8_t> data,HdrMetadata * hdr_metadata)646 size_t ColorSpaceExtension::ParseHdrMetadata(rtc::ArrayView<const uint8_t> data,
647                                              HdrMetadata* hdr_metadata) {
648   RTC_DCHECK_EQ(data.size(),
649                 kValueSizeBytes - kValueSizeBytesWithoutHdrMetadata);
650   size_t offset = 0;
651   offset += ParseLuminance(data.data() + offset,
652                            &hdr_metadata->mastering_metadata.luminance_max,
653                            kLuminanceMaxDenominator);
654   offset += ParseLuminance(data.data() + offset,
655                            &hdr_metadata->mastering_metadata.luminance_min,
656                            kLuminanceMinDenominator);
657   offset += ParseChromaticity(data.data() + offset,
658                               &hdr_metadata->mastering_metadata.primary_r);
659   offset += ParseChromaticity(data.data() + offset,
660                               &hdr_metadata->mastering_metadata.primary_g);
661   offset += ParseChromaticity(data.data() + offset,
662                               &hdr_metadata->mastering_metadata.primary_b);
663   offset += ParseChromaticity(data.data() + offset,
664                               &hdr_metadata->mastering_metadata.white_point);
665   hdr_metadata->max_content_light_level =
666       ByteReader<uint16_t>::ReadBigEndian(data.data() + offset);
667   offset += 2;
668   hdr_metadata->max_frame_average_light_level =
669       ByteReader<uint16_t>::ReadBigEndian(data.data() + offset);
670   offset += 2;
671   return offset;
672 }
673 
ParseChromaticity(const uint8_t * data,HdrMasteringMetadata::Chromaticity * p)674 size_t ColorSpaceExtension::ParseChromaticity(
675     const uint8_t* data,
676     HdrMasteringMetadata::Chromaticity* p) {
677   uint16_t chromaticity_x_scaled = ByteReader<uint16_t>::ReadBigEndian(data);
678   uint16_t chromaticity_y_scaled =
679       ByteReader<uint16_t>::ReadBigEndian(data + 2);
680   p->x = static_cast<float>(chromaticity_x_scaled) / kChromaticityDenominator;
681   p->y = static_cast<float>(chromaticity_y_scaled) / kChromaticityDenominator;
682   return 4;  // Return number of bytes read.
683 }
684 
ParseLuminance(const uint8_t * data,float * f,int denominator)685 size_t ColorSpaceExtension::ParseLuminance(const uint8_t* data,
686                                            float* f,
687                                            int denominator) {
688   uint16_t luminance_scaled = ByteReader<uint16_t>::ReadBigEndian(data);
689   *f = static_cast<float>(luminance_scaled) / denominator;
690   return 2;  // Return number of bytes read.
691 }
692 
WriteHdrMetadata(rtc::ArrayView<uint8_t> data,const HdrMetadata & hdr_metadata)693 size_t ColorSpaceExtension::WriteHdrMetadata(rtc::ArrayView<uint8_t> data,
694                                              const HdrMetadata& hdr_metadata) {
695   RTC_DCHECK_EQ(data.size(),
696                 kValueSizeBytes - kValueSizeBytesWithoutHdrMetadata);
697   RTC_DCHECK(hdr_metadata.Validate());
698   size_t offset = 0;
699   offset += WriteLuminance(data.data() + offset,
700                            hdr_metadata.mastering_metadata.luminance_max,
701                            kLuminanceMaxDenominator);
702   offset += WriteLuminance(data.data() + offset,
703                            hdr_metadata.mastering_metadata.luminance_min,
704                            kLuminanceMinDenominator);
705   offset += WriteChromaticity(data.data() + offset,
706                               hdr_metadata.mastering_metadata.primary_r);
707   offset += WriteChromaticity(data.data() + offset,
708                               hdr_metadata.mastering_metadata.primary_g);
709   offset += WriteChromaticity(data.data() + offset,
710                               hdr_metadata.mastering_metadata.primary_b);
711   offset += WriteChromaticity(data.data() + offset,
712                               hdr_metadata.mastering_metadata.white_point);
713 
714   ByteWriter<uint16_t>::WriteBigEndian(data.data() + offset,
715                                        hdr_metadata.max_content_light_level);
716   offset += 2;
717   ByteWriter<uint16_t>::WriteBigEndian(
718       data.data() + offset, hdr_metadata.max_frame_average_light_level);
719   offset += 2;
720   return offset;
721 }
722 
WriteChromaticity(uint8_t * data,const HdrMasteringMetadata::Chromaticity & p)723 size_t ColorSpaceExtension::WriteChromaticity(
724     uint8_t* data,
725     const HdrMasteringMetadata::Chromaticity& p) {
726   RTC_DCHECK_GE(p.x, 0.0f);
727   RTC_DCHECK_LE(p.x, 1.0f);
728   RTC_DCHECK_GE(p.y, 0.0f);
729   RTC_DCHECK_LE(p.y, 1.0f);
730   ByteWriter<uint16_t>::WriteBigEndian(
731       data, std::round(p.x * kChromaticityDenominator));
732   ByteWriter<uint16_t>::WriteBigEndian(
733       data + 2, std::round(p.y * kChromaticityDenominator));
734   return 4;  // Return number of bytes written.
735 }
736 
WriteLuminance(uint8_t * data,float f,int denominator)737 size_t ColorSpaceExtension::WriteLuminance(uint8_t* data,
738                                            float f,
739                                            int denominator) {
740   RTC_DCHECK_GE(f, 0.0f);
741   float upscaled_value = f * denominator;
742   RTC_DCHECK_LE(upscaled_value, std::numeric_limits<uint16_t>::max());
743   ByteWriter<uint16_t>::WriteBigEndian(data, std::round(upscaled_value));
744   return 2;  // Return number of bytes written.
745 }
746 
Parse(rtc::ArrayView<const uint8_t> data,std::string * str)747 bool BaseRtpStringExtension::Parse(rtc::ArrayView<const uint8_t> data,
748                                    std::string* str) {
749   if (data.empty() || data[0] == 0)  // Valid string extension can't be empty.
750     return false;
751   const char* cstr = reinterpret_cast<const char*>(data.data());
752   // If there is a \0 character in the middle of the |data|, treat it as end
753   // of the string. Well-formed string extensions shouldn't contain it.
754   str->assign(cstr, strnlen(cstr, data.size()));
755   RTC_DCHECK(!str->empty());
756   return true;
757 }
758 
Write(rtc::ArrayView<uint8_t> data,const std::string & str)759 bool BaseRtpStringExtension::Write(rtc::ArrayView<uint8_t> data,
760                                    const std::string& str) {
761   if (str.size() > kMaxValueSizeBytes) {
762     return false;
763   }
764   RTC_DCHECK_EQ(data.size(), str.size());
765   RTC_DCHECK_GE(str.size(), 1);
766   memcpy(data.data(), str.data(), str.size());
767   return true;
768 }
769 
770 // Constant declarations for string RTP header extension types.
771 
772 constexpr RTPExtensionType RtpStreamId::kId;
773 constexpr const char RtpStreamId::kUri[];
774 
775 constexpr RTPExtensionType RepairedRtpStreamId::kId;
776 constexpr const char RepairedRtpStreamId::kUri[];
777 
778 constexpr RTPExtensionType RtpMid::kId;
779 constexpr const char RtpMid::kUri[];
780 
781 // An RTP Header Extension for Inband Comfort Noise
782 //
783 // The form of the audio level extension block:
784 //
785 //  0                   1
786 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
787 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
788 // |  ID   | len=0 |N| level       |
789 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
790 // Sample Audio Level Encoding Using the One-Byte Header Format
791 //
792 //  0                   1                   2
793 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
794 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
795 // |      ID       |     len=1     |N|    level    |
796 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
797 // Sample Audio Level Encoding Using the Two-Byte Header Format
798 
799 constexpr RTPExtensionType InbandComfortNoiseExtension::kId;
800 constexpr uint8_t InbandComfortNoiseExtension::kValueSizeBytes;
801 constexpr const char InbandComfortNoiseExtension::kUri[];
802 
Parse(rtc::ArrayView<const uint8_t> data,absl::optional<uint8_t> * level)803 bool InbandComfortNoiseExtension::Parse(rtc::ArrayView<const uint8_t> data,
804                                         absl::optional<uint8_t>* level) {
805   if (data.size() != kValueSizeBytes)
806     return false;
807   *level = (data[0] & 0b1000'0000) != 0
808                ? absl::nullopt
809                : absl::make_optional(data[0] & 0b0111'1111);
810   return true;
811 }
812 
Write(rtc::ArrayView<uint8_t> data,absl::optional<uint8_t> level)813 bool InbandComfortNoiseExtension::Write(rtc::ArrayView<uint8_t> data,
814                                         absl::optional<uint8_t> level) {
815   RTC_DCHECK_EQ(data.size(), kValueSizeBytes);
816   data[0] = 0b0000'0000;
817   if (level) {
818     if (*level > 127) {
819       return false;
820     }
821     data[0] = 0b1000'0000 | *level;
822   }
823   return true;
824 }
825 
826 }  // namespace webrtc
827