blob: e38b3a3b4346b5dbd9b29a02346c3fc77459b4db [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
danilchapf6975f42015-12-28 10:18:46 -080013#include <string.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Peter Boströmebc0b4e2015-10-28 16:39:33 +010015#include "webrtc/base/logging.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000016#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000017
niklase@google.com470e71d2011-07-07 08:21:25 +000018namespace webrtc {
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000019
wu@webrtc.org822fbd82013-08-15 23:38:54 +000020RtpData* NullObjectRtpData() {
21 static NullRtpData null_rtp_data;
22 return &null_rtp_data;
23}
24
25RtpFeedback* NullObjectRtpFeedback() {
26 static NullRtpFeedback null_rtp_feedback;
27 return &null_rtp_feedback;
28}
29
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +000030ReceiveStatistics* NullObjectReceiveStatistics() {
31 static NullReceiveStatistics null_receive_statistics;
32 return &null_receive_statistics;
33}
34
pbos@webrtc.org62bafae2014-07-08 12:10:51 +000035namespace RtpUtility {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000036
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +000037enum {
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +000038 kRtcpExpectedVersion = 2,
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +000039 kRtcpMinHeaderLength = 4,
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +000040 kRtcpMinParseLength = 8,
41
42 kRtpExpectedVersion = 2,
43 kRtpMinParseLength = 12
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +000044};
45
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000046/*
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000047 * Misc utility routines
48 */
49
50#if defined(_WIN32)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000051bool StringCompare(const char* str1, const char* str2,
pbos@webrtc.org2f446732013-04-08 11:08:41 +000052 const uint32_t length) {
danilchapf6975f42015-12-28 10:18:46 -080053 return _strnicmp(str1, str2, length) == 0;
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000054}
55#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000056bool StringCompare(const char* str1, const char* str2,
pbos@webrtc.org2f446732013-04-08 11:08:41 +000057 const uint32_t length) {
danilchapf6975f42015-12-28 10:18:46 -080058 return strncasecmp(str1, str2, length) == 0;
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +000059}
60#endif
niklase@google.com470e71d2011-07-07 08:21:25 +000061
sprang@webrtc.org30933902015-03-17 14:33:12 +000062size_t Word32Align(size_t size) {
63 uint32_t remainder = size % 4;
64 if (remainder != 0)
65 return size + 4 - remainder;
66 return size;
67}
68
pbos@webrtc.org62bafae2014-07-08 12:10:51 +000069RtpHeaderParser::RtpHeaderParser(const uint8_t* rtpData,
70 const size_t rtpDataLength)
71 : _ptrRTPDataBegin(rtpData),
72 _ptrRTPDataEnd(rtpData ? (rtpData + rtpDataLength) : NULL) {
niklase@google.com470e71d2011-07-07 08:21:25 +000073}
74
pbos@webrtc.org62bafae2014-07-08 12:10:51 +000075RtpHeaderParser::~RtpHeaderParser() {
niklase@google.com470e71d2011-07-07 08:21:25 +000076}
77
pbos@webrtc.org62bafae2014-07-08 12:10:51 +000078bool RtpHeaderParser::RTCP() const {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +000079 // 72 to 76 is reserved for RTP
80 // 77 to 79 is not reserver but they are not assigned we will block them
81 // for RTCP 200 SR == marker bit + 72
82 // for RTCP 204 APP == marker bit + 76
83 /*
84 * RTCP
85 *
86 * FIR full INTRA-frame request 192 [RFC2032] supported
87 * NACK negative acknowledgement 193 [RFC2032]
88 * IJ Extended inter-arrival jitter report 195 [RFC-ietf-avt-rtp-toff
89 * set-07.txt] http://tools.ietf.org/html/draft-ietf-avt-rtp-toffset-07
90 * SR sender report 200 [RFC3551] supported
91 * RR receiver report 201 [RFC3551] supported
92 * SDES source description 202 [RFC3551] supported
93 * BYE goodbye 203 [RFC3551] supported
94 * APP application-defined 204 [RFC3551] ignored
95 * RTPFB Transport layer FB message 205 [RFC4585] supported
96 * PSFB Payload-specific FB message 206 [RFC4585] supported
97 * XR extended report 207 [RFC3611] supported
98 */
niklase@google.com470e71d2011-07-07 08:21:25 +000099
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000100 /* 205 RFC 5104
101 * FMT 1 NACK supported
102 * FMT 2 reserved
103 * FMT 3 TMMBR supported
104 * FMT 4 TMMBN supported
105 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000106
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000107 /* 206 RFC 5104
108 * FMT 1: Picture Loss Indication (PLI) supported
109 * FMT 2: Slice Lost Indication (SLI)
110 * FMT 3: Reference Picture Selection Indication (RPSI)
111 * FMT 4: Full Intra Request (FIR) Command supported
112 * FMT 5: Temporal-Spatial Trade-off Request (TSTR)
113 * FMT 6: Temporal-Spatial Trade-off Notification (TSTN)
114 * FMT 7: Video Back Channel Message (VBCM)
115 * FMT 15: Application layer FB message
116 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000117
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +0000118 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
119 if (length < kRtcpMinHeaderLength) {
120 return false;
121 }
122
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000123 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
solenberg@webrtc.orgd8a6e722013-03-26 14:02:30 +0000124 if (V != kRtcpExpectedVersion) {
125 return false;
126 }
127
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000128 const uint8_t payloadType = _ptrRTPDataBegin[1];
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000129 switch (payloadType) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000130 case 192:
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000131 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000132 case 193:
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000133 // not supported
134 // pass through and check for a potential RTP packet
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000135 return false;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000136 case 195:
niklase@google.com470e71d2011-07-07 08:21:25 +0000137 case 200:
138 case 201:
139 case 202:
140 case 203:
141 case 204:
142 case 205:
143 case 206:
144 case 207:
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000145 return true;
146 default:
147 return false;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000148 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000149}
150
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000151bool RtpHeaderParser::ParseRtcp(RTPHeader* header) const {
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +0000152 assert(header != NULL);
153
154 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
155 if (length < kRtcpMinParseLength) {
156 return false;
157 }
158
159 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
160 if (V != kRtcpExpectedVersion) {
161 return false;
162 }
163
164 const uint8_t PT = _ptrRTPDataBegin[1];
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000165 const size_t len = (_ptrRTPDataBegin[2] << 8) + _ptrRTPDataBegin[3];
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +0000166 const uint8_t* ptr = &_ptrRTPDataBegin[4];
167
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000168 uint32_t SSRC = ByteReader<uint32_t>::ReadBigEndian(ptr);
169 ptr += 4;
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +0000170
171 header->payloadType = PT;
172 header->ssrc = SSRC;
173 header->headerLength = 4 + (len << 2);
174
175 return true;
176}
177
danilchapf6975f42015-12-28 10:18:46 -0800178bool RtpHeaderParser::Parse(RTPHeader* header,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000179 RtpHeaderExtensionMap* ptrExtensionMap) const {
180 const ptrdiff_t length = _ptrRTPDataEnd - _ptrRTPDataBegin;
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +0000181 if (length < kRtpMinParseLength) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000182 return false;
183 }
184
185 // Version
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000186 const uint8_t V = _ptrRTPDataBegin[0] >> 6;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000187 // Padding
188 const bool P = ((_ptrRTPDataBegin[0] & 0x20) == 0) ? false : true;
189 // eXtension
190 const bool X = ((_ptrRTPDataBegin[0] & 0x10) == 0) ? false : true;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000191 const uint8_t CC = _ptrRTPDataBegin[0] & 0x0f;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000192 const bool M = ((_ptrRTPDataBegin[1] & 0x80) == 0) ? false : true;
193
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000194 const uint8_t PT = _ptrRTPDataBegin[1] & 0x7f;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000195
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000196 const uint16_t sequenceNumber = (_ptrRTPDataBegin[2] << 8) +
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000197 _ptrRTPDataBegin[3];
198
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000199 const uint8_t* ptr = &_ptrRTPDataBegin[4];
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000200
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000201 uint32_t RTPTimestamp = ByteReader<uint32_t>::ReadBigEndian(ptr);
202 ptr += 4;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000203
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000204 uint32_t SSRC = ByteReader<uint32_t>::ReadBigEndian(ptr);
205 ptr += 4;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000206
solenberg@webrtc.orga5fd2f12013-06-26 08:36:07 +0000207 if (V != kRtpExpectedVersion) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000208 return false;
209 }
210
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000211 const size_t CSRCocts = CC * 4;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000212
213 if ((ptr + CSRCocts) > _ptrRTPDataEnd) {
214 return false;
215 }
216
danilchapf6975f42015-12-28 10:18:46 -0800217 header->markerBit = M;
218 header->payloadType = PT;
219 header->sequenceNumber = sequenceNumber;
220 header->timestamp = RTPTimestamp;
221 header->ssrc = SSRC;
222 header->numCSRCs = CC;
223 header->paddingLength = P ? *(_ptrRTPDataEnd - 1) : 0;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000224
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000225 for (uint8_t i = 0; i < CC; ++i) {
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000226 uint32_t CSRC = ByteReader<uint32_t>::ReadBigEndian(ptr);
227 ptr += 4;
danilchapf6975f42015-12-28 10:18:46 -0800228 header->arrOfCSRCs[i] = CSRC;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000229 }
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000230
danilchapf6975f42015-12-28 10:18:46 -0800231 header->headerLength = 12 + CSRCocts;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000232
233 // If in effect, MAY be omitted for those packets for which the offset
234 // is zero.
danilchapf6975f42015-12-28 10:18:46 -0800235 header->extension.hasTransmissionTimeOffset = false;
236 header->extension.transmissionTimeOffset = 0;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000237
solenberg@webrtc.org7ebbea12013-05-16 11:10:31 +0000238 // May not be present in packet.
danilchapf6975f42015-12-28 10:18:46 -0800239 header->extension.hasAbsoluteSendTime = false;
240 header->extension.absoluteSendTime = 0;
solenberg@webrtc.org7ebbea12013-05-16 11:10:31 +0000241
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +0000242 // May not be present in packet.
danilchapf6975f42015-12-28 10:18:46 -0800243 header->extension.hasAudioLevel = false;
244 header->extension.voiceActivity = false;
245 header->extension.audioLevel = 0;
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +0000246
guoweis@webrtc.org45362892015-03-04 22:55:15 +0000247 // May not be present in packet.
danilchapf6975f42015-12-28 10:18:46 -0800248 header->extension.hasVideoRotation = false;
249 header->extension.videoRotation = 0;
guoweis@webrtc.org45362892015-03-04 22:55:15 +0000250
isheriff6b4b5f32016-06-08 00:24:21 -0700251 // May not be present in packet.
252 header->extension.playout_delay.min_ms = -1;
253 header->extension.playout_delay.max_ms = -1;
254
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000255 if (X) {
256 /* RTP header extension, RFC 3550.
257 0 1 2 3
258 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
259 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
260 | defined by profile | length |
261 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
262 | header extension |
263 | .... |
264 */
265 const ptrdiff_t remain = _ptrRTPDataEnd - ptr;
266 if (remain < 4) {
267 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000268 }
269
danilchapf6975f42015-12-28 10:18:46 -0800270 header->headerLength += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000271
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000272 uint16_t definedByProfile = ByteReader<uint16_t>::ReadBigEndian(ptr);
273 ptr += 2;
niklase@google.com470e71d2011-07-07 08:21:25 +0000274
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000275 // in 32 bit words
276 size_t XLen = ByteReader<uint16_t>::ReadBigEndian(ptr);
277 ptr += 2;
278 XLen *= 4; // in bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000279
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000280 if (static_cast<size_t>(remain) < (4 + XLen)) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000281 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000282 }
pbos@webrtc.org3004c792013-05-07 12:36:21 +0000283 if (definedByProfile == kRtpOneByteHeaderExtensionId) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000284 const uint8_t* ptrRTPDataExtensionEnd = ptr + XLen;
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +0000285 ParseOneByteExtensionHeader(header,
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000286 ptrExtensionMap,
287 ptrRTPDataExtensionEnd,
288 ptr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000289 }
danilchapf6975f42015-12-28 10:18:46 -0800290 header->headerLength += XLen;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000291 }
danilchapf6975f42015-12-28 10:18:46 -0800292 if (header->headerLength + header->paddingLength >
293 static_cast<size_t>(length))
pbosbd2522a2015-07-01 05:35:53 -0700294 return false;
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000295 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000296}
297
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000298void RtpHeaderParser::ParseOneByteExtensionHeader(
danilchapf6975f42015-12-28 10:18:46 -0800299 RTPHeader* header,
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000300 const RtpHeaderExtensionMap* ptrExtensionMap,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000301 const uint8_t* ptrRTPDataExtensionEnd,
302 const uint8_t* ptr) const {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000303 if (!ptrExtensionMap) {
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000304 return;
305 }
306
307 while (ptrRTPDataExtensionEnd - ptr > 0) {
308 // 0
309 // 0 1 2 3 4 5 6 7
310 // +-+-+-+-+-+-+-+-+
311 // | ID | len |
312 // +-+-+-+-+-+-+-+-+
313
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000314 // Note that 'len' is the header extension element length, which is the
315 // number of bytes - 1.
Stefan Holmer3842c5c2016-01-12 13:55:00 +0100316 const int id = (*ptr & 0xf0) >> 4;
317 const int len = (*ptr & 0x0f);
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000318 ptr++;
319
320 if (id == 15) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000321 LOG(LS_WARNING)
322 << "RTP extension header 15 encountered. Terminate parsing.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000323 return;
324 }
325
Danil Chapovalov30a3a752016-06-16 15:57:15 +0200326 if (ptrRTPDataExtensionEnd - ptr < (len + 1)) {
327 LOG(LS_WARNING) << "Incorrect one-byte extension len: " << (len + 1)
328 << ", bytes left in buffer: "
329 << (ptrRTPDataExtensionEnd - ptr);
330 return;
331 }
332
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000333 RTPExtensionType type;
334 if (ptrExtensionMap->GetType(id, &type) != 0) {
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000335 // If we encounter an unknown extension, just skip over it.
Stefan Holmer3842c5c2016-01-12 13:55:00 +0100336 LOG(LS_WARNING) << "Failed to find extension id: " << id;
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000337 } else {
338 switch (type) {
339 case kRtpExtensionTransmissionTimeOffset: {
340 if (len != 2) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000341 LOG(LS_WARNING) << "Incorrect transmission time offset len: "
342 << len;
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000343 return;
344 }
345 // 0 1 2 3
346 // 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
347 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
348 // | ID | len=2 | transmission offset |
349 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000350
danilchapf6975f42015-12-28 10:18:46 -0800351 header->extension.transmissionTimeOffset =
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000352 ByteReader<int32_t, 3>::ReadBigEndian(ptr);
danilchapf6975f42015-12-28 10:18:46 -0800353 header->extension.hasTransmissionTimeOffset = true;
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000354 break;
355 }
356 case kRtpExtensionAudioLevel: {
357 if (len != 0) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000358 LOG(LS_WARNING) << "Incorrect audio level len: " << len;
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000359 return;
360 }
sprang@webrtc.org30933902015-03-17 14:33:12 +0000361 // 0 1
362 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
363 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
364 // | ID | len=0 |V| level |
365 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000366 //
danilchapf6975f42015-12-28 10:18:46 -0800367 header->extension.audioLevel = ptr[0] & 0x7f;
368 header->extension.voiceActivity = (ptr[0] & 0x80) != 0;
369 header->extension.hasAudioLevel = true;
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000370 break;
371 }
372 case kRtpExtensionAbsoluteSendTime: {
373 if (len != 2) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000374 LOG(LS_WARNING) << "Incorrect absolute send time len: " << len;
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000375 return;
376 }
377 // 0 1 2 3
378 // 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
379 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
380 // | ID | len=2 | absolute send time |
381 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
382
danilchapf6975f42015-12-28 10:18:46 -0800383 header->extension.absoluteSendTime =
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000384 ByteReader<uint32_t, 3>::ReadBigEndian(ptr);
danilchapf6975f42015-12-28 10:18:46 -0800385 header->extension.hasAbsoluteSendTime = true;
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000386 break;
387 }
guoweis@webrtc.org45362892015-03-04 22:55:15 +0000388 case kRtpExtensionVideoRotation: {
389 if (len != 0) {
390 LOG(LS_WARNING)
391 << "Incorrect coordination of video coordination len: " << len;
392 return;
393 }
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000394 // 0 1
395 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
396 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
397 // | ID | len=0 |0 0 0 0 C F R R|
398 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
danilchapf6975f42015-12-28 10:18:46 -0800399 header->extension.hasVideoRotation = true;
400 header->extension.videoRotation = ptr[0];
guoweis@webrtc.org45362892015-03-04 22:55:15 +0000401 break;
402 }
sprang@webrtc.org30933902015-03-17 14:33:12 +0000403 case kRtpExtensionTransportSequenceNumber: {
404 if (len != 1) {
Stefan Holmer3842c5c2016-01-12 13:55:00 +0100405 LOG(LS_WARNING) << "Incorrect transport sequence number len: "
406 << len;
sprang@webrtc.org30933902015-03-17 14:33:12 +0000407 return;
408 }
409 // 0 1 2
410 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
411 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
412 // | ID | L=1 |transport wide sequence number |
413 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
414
415 uint16_t sequence_number = ptr[0] << 8;
416 sequence_number += ptr[1];
danilchapf6975f42015-12-28 10:18:46 -0800417 header->extension.transportSequenceNumber = sequence_number;
418 header->extension.hasTransportSequenceNumber = true;
sprang@webrtc.org30933902015-03-17 14:33:12 +0000419 break;
420 }
isheriff6b4b5f32016-06-08 00:24:21 -0700421 case kRtpExtensionPlayoutDelay: {
422 if (len != 2) {
423 LOG(LS_WARNING) << "Incorrect playout delay len: " << len;
424 return;
425 }
426 // 0 1 2 3
427 // 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
428 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
429 // | ID | len=2 | MIN delay | MAX delay |
430 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
431
432 int min_playout_delay = (ptr[0] << 4) | ((ptr[1] >> 4) & 0xf);
433 int max_playout_delay = ((ptr[1] & 0xf) << 8) | ptr[2];
434 header->extension.playout_delay.min_ms =
435 min_playout_delay * kPlayoutDelayGranularityMs;
436 header->extension.playout_delay.max_ms =
437 max_playout_delay * kPlayoutDelayGranularityMs;
438 break;
439 }
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000440 default: {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000441 LOG(LS_WARNING) << "Extension type not implemented: " << type;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000442 return;
443 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000444 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000445 }
solenberg@webrtc.org440fa232014-03-25 19:57:07 +0000446 ptr += (len + 1);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000447 uint8_t num_bytes = ParsePaddingBytes(ptrRTPDataExtensionEnd, ptr);
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000448 ptr += num_bytes;
449 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000450}
451
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000452uint8_t RtpHeaderParser::ParsePaddingBytes(
453 const uint8_t* ptrRTPDataExtensionEnd,
454 const uint8_t* ptr) const {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000455 uint8_t num_zero_bytes = 0;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000456 while (ptrRTPDataExtensionEnd - ptr > 0) {
457 if (*ptr != 0) {
458 return num_zero_bytes;
459 }
460 ptr++;
461 num_zero_bytes++;
462 }
463 return num_zero_bytes;
464}
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000465} // namespace RtpUtility
henrike@webrtc.orgd5657c22012-02-08 23:41:49 +0000466} // namespace webrtc