Line data Source code
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 "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
12 :
13 : #include "webrtc/base/checks.h"
14 : #include "webrtc/base/logging.h"
15 : #include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
16 : #include "webrtc/modules/rtp_rtcp/source/byte_io.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 :
38 0 : bool AbsoluteSendTime::Parse(const uint8_t* data, uint32_t* time_24bits) {
39 0 : *time_24bits = ByteReader<uint32_t, 3>::ReadBigEndian(data);
40 0 : return true;
41 : }
42 :
43 0 : bool AbsoluteSendTime::Write(uint8_t* data, int64_t time_ms) {
44 0 : ByteWriter<uint32_t, 3>::WriteBigEndian(data, MsTo24Bits(time_ms));
45 0 : return true;
46 : }
47 :
48 : // An RTP Header Extension for Client-to-Mixer Audio Level Indication
49 : //
50 : // https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
51 : //
52 : // The form of the audio level extension block:
53 : //
54 : // 0 1
55 : // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
56 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 : // | ID | len=0 |V| level |
58 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 : //
60 : constexpr RTPExtensionType AudioLevel::kId;
61 : constexpr uint8_t AudioLevel::kValueSizeBytes;
62 : constexpr const char* AudioLevel::kUri;
63 :
64 0 : bool AudioLevel::Parse(const uint8_t* data,
65 : bool* voice_activity,
66 : uint8_t* audio_level) {
67 0 : *voice_activity = (data[0] & 0x80) != 0;
68 0 : *audio_level = data[0] & 0x7F;
69 0 : return true;
70 : }
71 :
72 0 : bool AudioLevel::Write(uint8_t* data,
73 : bool voice_activity,
74 : uint8_t audio_level) {
75 0 : RTC_CHECK_LE(audio_level, 0x7f);
76 0 : data[0] = (voice_activity ? 0x80 : 0x00) | audio_level;
77 0 : return true;
78 : }
79 :
80 : // From RFC 5450: Transmission Time Offsets in RTP Streams.
81 : //
82 : // The transmission time is signaled to the receiver in-band using the
83 : // general mechanism for RTP header extensions [RFC5285]. The payload
84 : // of this extension (the transmitted value) is a 24-bit signed integer.
85 : // When added to the RTP timestamp of the packet, it represents the
86 : // "effective" RTP transmission time of the packet, on the RTP
87 : // timescale.
88 : //
89 : // The form of the transmission offset extension block:
90 : //
91 : // 0 1 2 3
92 : // 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
93 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 : // | ID | len=2 | transmission offset |
95 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96 : constexpr RTPExtensionType TransmissionOffset::kId;
97 : constexpr uint8_t TransmissionOffset::kValueSizeBytes;
98 : constexpr const char* TransmissionOffset::kUri;
99 :
100 0 : bool TransmissionOffset::Parse(const uint8_t* data, int32_t* rtp_time) {
101 0 : *rtp_time = ByteReader<int32_t, 3>::ReadBigEndian(data);
102 0 : return true;
103 : }
104 :
105 0 : bool TransmissionOffset::Write(uint8_t* data, int32_t rtp_time) {
106 0 : RTC_DCHECK_LE(rtp_time, 0x00ffffff);
107 0 : ByteWriter<int32_t, 3>::WriteBigEndian(data, rtp_time);
108 0 : return true;
109 : }
110 :
111 : // 0 1 2
112 : // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
113 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114 : // | ID | L=1 |transport wide sequence number |
115 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116 : constexpr RTPExtensionType TransportSequenceNumber::kId;
117 : constexpr uint8_t TransportSequenceNumber::kValueSizeBytes;
118 : constexpr const char* TransportSequenceNumber::kUri;
119 :
120 0 : bool TransportSequenceNumber::Parse(const uint8_t* data, uint16_t* value) {
121 0 : *value = ByteReader<uint16_t>::ReadBigEndian(data);
122 0 : return true;
123 : }
124 :
125 0 : bool TransportSequenceNumber::Write(uint8_t* data, uint16_t value) {
126 0 : ByteWriter<uint16_t>::WriteBigEndian(data, value);
127 0 : return true;
128 : }
129 :
130 : // Coordination of Video Orientation in RTP streams.
131 : //
132 : // Coordination of Video Orientation consists in signaling of the current
133 : // orientation of the image captured on the sender side to the receiver for
134 : // appropriate rendering and displaying.
135 : //
136 : // 0 1
137 : // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
138 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139 : // | ID | len=0 |0 0 0 0 C F R R|
140 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
141 : constexpr RTPExtensionType VideoOrientation::kId;
142 : constexpr uint8_t VideoOrientation::kValueSizeBytes;
143 : constexpr const char* VideoOrientation::kUri;
144 :
145 0 : bool VideoOrientation::Parse(const uint8_t* data, VideoRotation* rotation) {
146 0 : *rotation = ConvertCVOByteToVideoRotation(data[0]);
147 0 : return true;
148 : }
149 :
150 0 : bool VideoOrientation::Write(uint8_t* data, VideoRotation rotation) {
151 0 : data[0] = ConvertVideoRotationToCVOByte(rotation);
152 0 : return true;
153 : }
154 :
155 0 : bool VideoOrientation::Parse(const uint8_t* data, uint8_t* value) {
156 0 : *value = data[0];
157 0 : return true;
158 : }
159 :
160 0 : bool VideoOrientation::Write(uint8_t* data, uint8_t value) {
161 0 : data[0] = value;
162 0 : return true;
163 : }
164 :
165 : // 0 1 2 3
166 : // 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
167 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
168 : // | ID | len=2 | MIN delay | MAX delay |
169 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
170 : constexpr RTPExtensionType PlayoutDelayLimits::kId;
171 : constexpr uint8_t PlayoutDelayLimits::kValueSizeBytes;
172 : constexpr const char* PlayoutDelayLimits::kUri;
173 :
174 0 : bool PlayoutDelayLimits::Parse(const uint8_t* data,
175 : PlayoutDelay* playout_delay) {
176 0 : RTC_DCHECK(playout_delay);
177 0 : uint32_t raw = ByteReader<uint32_t, 3>::ReadBigEndian(data);
178 0 : uint16_t min_raw = (raw >> 12);
179 0 : uint16_t max_raw = (raw & 0xfff);
180 0 : if (min_raw > max_raw)
181 0 : return false;
182 0 : playout_delay->min_ms = min_raw * kGranularityMs;
183 0 : playout_delay->max_ms = max_raw * kGranularityMs;
184 0 : return true;
185 : }
186 :
187 0 : bool PlayoutDelayLimits::Write(uint8_t* data,
188 : const PlayoutDelay& playout_delay) {
189 0 : RTC_DCHECK_LE(0, playout_delay.min_ms);
190 0 : RTC_DCHECK_LE(playout_delay.min_ms, playout_delay.max_ms);
191 0 : RTC_DCHECK_LE(playout_delay.max_ms, kMaxMs);
192 : // Convert MS to value to be sent on extension header.
193 0 : uint32_t min_delay = playout_delay.min_ms / kGranularityMs;
194 0 : uint32_t max_delay = playout_delay.max_ms / kGranularityMs;
195 0 : ByteWriter<uint32_t, 3>::WriteBigEndian(data, (min_delay << 12) | max_delay);
196 0 : return true;
197 : }
198 :
199 : // 0 1 2
200 : // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
201 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202 : // | ID | L=? |UTF-8 RID value...... |...
203 : // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204 : constexpr RTPExtensionType StreamId::kId;
205 : constexpr uint8_t StreamId::kValueSizeBytes;
206 : constexpr const char* StreamId::kUri;
207 :
208 0 : bool StreamId::Parse(const uint8_t* data, char rid[kRIDSize+1]) {
209 0 : uint8_t len = (data[0] & 0x0F) + 1;
210 0 : memcpy(rid, &data[1], len);
211 0 : rid[len] = '\0';
212 0 : return true;
213 : }
214 :
215 0 : bool StreamId::Write(uint8_t* data, const char *rid) {
216 : // XXX FIX! how to get it to modify the length? data points to the RID value
217 0 : int len = strlen(rid);
218 0 : RTC_DCHECK(len > 0 && len <= 16);
219 0 : if (len > 16) {
220 0 : len = 16;
221 0 : } else if (len == 0) {
222 : // really bad, but don't blow up
223 0 : rid = "x";
224 0 : len = 1;
225 : }
226 0 : memcpy(data, rid, len);
227 0 : return true;
228 : }
229 :
230 : } // namespace webrtc
|