blob: 3d44fbcb25377e59d50a2eec9130bded64668fac [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
2 * Copyright (c) 2012 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 "NETEQTEST_RTPpacket.h"
12
13#include <assert.h>
14#include <stdlib.h> // rand
15#include <string.h>
16
17#ifdef WIN32
18#include <winsock2.h>
19#else
20#include <netinet/in.h> // for htons, htonl, etc
21#endif
22
23const int NETEQTEST_RTPpacket::_kRDHeaderLen = 8;
24const int NETEQTEST_RTPpacket::_kBasicHeaderLen = 12;
25
26NETEQTEST_RTPpacket::NETEQTEST_RTPpacket()
27:
28_datagram(NULL),
29_payloadPtr(NULL),
30_memSize(0),
31_datagramLen(-1),
32_payloadLen(0),
33_rtpParsed(false),
34_receiveTime(0),
35_lost(false)
36{
37 memset(&_rtpInfo, 0, sizeof(_rtpInfo));
38 _blockList.clear();
39}
40
41NETEQTEST_RTPpacket::~NETEQTEST_RTPpacket()
42{
43 if(_datagram)
44 {
45 delete [] _datagram;
46 }
47}
48
49void NETEQTEST_RTPpacket::reset()
50{
51 if(_datagram) {
52 delete [] _datagram;
53 }
54 _datagram = NULL;
55 _memSize = 0;
56 _datagramLen = -1;
57 _payloadLen = 0;
58 _payloadPtr = NULL;
59 _receiveTime = 0;
60 memset(&_rtpInfo, 0, sizeof(_rtpInfo));
61 _rtpParsed = false;
62
63}
64
65int NETEQTEST_RTPpacket::skipFileHeader(FILE *fp)
66{
67 if (!fp) {
68 return -1;
69 }
70
71 const int kFirstLineLength = 40;
72 char firstline[kFirstLineLength];
73 if (fgets(firstline, kFirstLineLength, fp) == NULL) {
74 return -1;
75 }
76 if (strncmp(firstline, "#!rtpplay", 9) == 0) {
77 if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) {
78 return -1;
79 }
80 }
81 else if (strncmp(firstline, "#!RTPencode", 11) == 0) {
82 if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) {
83 return -1;
84 }
85 }
86 else
87 {
88 return -1;
89 }
90
91 const int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
92 if (fseek(fp, kRtpDumpHeaderSize, SEEK_CUR) != 0)
93 {
94 return -1;
95 }
96 return 0;
97}
98
99int NETEQTEST_RTPpacket::readFromFile(FILE *fp)
100{
101 if(!fp)
102 {
103 return(-1);
104 }
105
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000106 uint16_t length, plen;
107 uint32_t offset;
fbarchard@google.comd7b4dea2014-08-05 23:46:42 +0000108 int packetLen = 0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000109
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000110 bool readNextPacket = true;
111 while (readNextPacket) {
112 readNextPacket = false;
113 if (fread(&length,2,1,fp)==0)
114 {
115 reset();
116 return(-2);
117 }
118 length = ntohs(length);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000119
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000120 if (fread(&plen,2,1,fp)==0)
121 {
122 reset();
123 return(-1);
124 }
125 packetLen = ntohs(plen);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000126
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000127 if (fread(&offset,4,1,fp)==0)
128 {
129 reset();
130 return(-1);
131 }
132 // store in local variable until we have passed the reset below
133 uint32_t receiveTime = ntohl(offset);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000134
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000135 // Use length here because a plen of 0 specifies rtcp
136 length = (uint16_t) (length - _kRDHeaderLen);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000137
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000138 // check buffer size
139 if (_datagram && _memSize < length)
140 {
141 reset();
142 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000143
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000144 if (!_datagram)
145 {
146 _datagram = new uint8_t[length];
147 _memSize = length;
148 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000149
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000150 if (fread((unsigned short *) _datagram,1,length,fp) != length)
151 {
152 reset();
153 return(-1);
154 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000155
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000156 _datagramLen = length;
157 _receiveTime = receiveTime;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000158
henrik.lundin@webrtc.org5ecdef12013-12-03 08:26:49 +0000159 if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
160 {
161 readNextPacket = true;
162 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000163 }
164
165 _rtpParsed = false;
166 return(packetLen);
167
168}
169
170
171int NETEQTEST_RTPpacket::readFixedFromFile(FILE *fp, size_t length)
172{
173 if (!fp)
174 {
175 return -1;
176 }
177
178 // check buffer size
179 if (_datagram && _memSize < static_cast<int>(length))
180 {
181 reset();
182 }
183
184 if (!_datagram)
185 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000186 _datagram = new uint8_t[length];
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000187 _memSize = length;
188 }
189
190 if (fread(_datagram, 1, length, fp) != length)
191 {
192 reset();
193 return -1;
194 }
195
196 _datagramLen = length;
197 _receiveTime = 0;
198
199 if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
200 {
201 // discard this payload
202 return readFromFile(fp);
203 }
204
205 _rtpParsed = false;
206 return length;
207
208}
209
210
211int NETEQTEST_RTPpacket::writeToFile(FILE *fp)
212{
213 if (!fp)
214 {
215 return -1;
216 }
217
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000218 uint16_t length, plen;
219 uint32_t offset;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000220
221 // length including RTPplay header
222 length = htons(_datagramLen + _kRDHeaderLen);
223 if (fwrite(&length, 2, 1, fp) != 1)
224 {
225 return -1;
226 }
227
228 // payload length
229 plen = htons(_datagramLen);
230 if (fwrite(&plen, 2, 1, fp) != 1)
231 {
232 return -1;
233 }
234
235 // offset (=receive time)
236 offset = htonl(_receiveTime);
237 if (fwrite(&offset, 4, 1, fp) != 1)
238 {
239 return -1;
240 }
241
242
243 // write packet data
244 if (fwrite(_datagram, 1, _datagramLen, fp) !=
245 static_cast<size_t>(_datagramLen))
246 {
247 return -1;
248 }
249
250 return _datagramLen + _kRDHeaderLen; // total number of bytes written
251
252}
253
254
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000255void NETEQTEST_RTPpacket::blockPT(uint8_t pt)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000256{
257 _blockList[pt] = true;
258}
259
260
261void NETEQTEST_RTPpacket::parseHeader()
262{
263 if (_rtpParsed)
264 {
265 // nothing to do
266 return;
267 }
268
269 if (_datagramLen < _kBasicHeaderLen)
270 {
271 // corrupt packet?
272 return;
273 }
274
275 _payloadLen = parseRTPheader(&_payloadPtr);
276
277 _rtpParsed = true;
278
279 return;
280
281}
282
283void NETEQTEST_RTPpacket::parseHeader(webrtc::WebRtcRTPHeader* rtp_header) {
284 if (!_rtpParsed) {
285 parseHeader();
286 }
287 if (rtp_header) {
288 rtp_header->header.markerBit = _rtpInfo.header.markerBit;
289 rtp_header->header.payloadType = _rtpInfo.header.payloadType;
290 rtp_header->header.sequenceNumber = _rtpInfo.header.sequenceNumber;
291 rtp_header->header.timestamp = _rtpInfo.header.timestamp;
292 rtp_header->header.ssrc = _rtpInfo.header.ssrc;
293 }
294}
295
296const webrtc::WebRtcRTPHeader* NETEQTEST_RTPpacket::RTPinfo() const
297{
298 if (_rtpParsed)
299 {
300 return &_rtpInfo;
301 }
302 else
303 {
304 return NULL;
305 }
306}
307
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000308uint8_t * NETEQTEST_RTPpacket::datagram() const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000309{
310 if (_datagramLen > 0)
311 {
312 return _datagram;
313 }
314 else
315 {
316 return NULL;
317 }
318}
319
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000320uint8_t * NETEQTEST_RTPpacket::payload() const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000321{
322 if (_payloadLen > 0)
323 {
324 return _payloadPtr;
325 }
326 else
327 {
328 return NULL;
329 }
330}
331
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000332size_t NETEQTEST_RTPpacket::payloadLen()
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000333{
334 parseHeader();
335 return _payloadLen;
336}
337
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000338int16_t NETEQTEST_RTPpacket::dataLen() const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000339{
340 return _datagramLen;
341}
342
343bool NETEQTEST_RTPpacket::isParsed() const
344{
345 return _rtpParsed;
346}
347
348bool NETEQTEST_RTPpacket::isLost() const
349{
350 return _lost;
351}
352
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000353uint8_t NETEQTEST_RTPpacket::payloadType() const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000354{
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000355 if(_datagram && _datagramLen >= _kBasicHeaderLen)
356 {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000357 webrtc::WebRtcRTPHeader tempRTPinfo;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000358 parseRTPheader(&tempRTPinfo);
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000359 return tempRTPinfo.header.payloadType;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000360 }
361 else
362 {
363 return 0;
364 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000365}
366
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000367uint16_t NETEQTEST_RTPpacket::sequenceNumber() const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000368{
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000369 if(_datagram && _datagramLen >= _kBasicHeaderLen)
370 {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000371 webrtc::WebRtcRTPHeader tempRTPinfo;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000372 parseRTPheader(&tempRTPinfo);
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000373 return tempRTPinfo.header.sequenceNumber;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000374 }
375 else
376 {
377 return 0;
378 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000379}
380
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000381uint32_t NETEQTEST_RTPpacket::timeStamp() const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000382{
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000383 if(_datagram && _datagramLen >= _kBasicHeaderLen)
384 {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000385 webrtc::WebRtcRTPHeader tempRTPinfo;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000386 parseRTPheader(&tempRTPinfo);
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000387 return tempRTPinfo.header.timestamp;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000388 }
389 else
390 {
391 return 0;
392 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000393}
394
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000395uint32_t NETEQTEST_RTPpacket::SSRC() const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000396{
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000397 if(_datagram && _datagramLen >= _kBasicHeaderLen)
398 {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000399 webrtc::WebRtcRTPHeader tempRTPinfo;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000400 parseRTPheader(&tempRTPinfo);
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000401 return tempRTPinfo.header.ssrc;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000402 }
403 else
404 {
405 return 0;
406 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000407}
408
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000409uint8_t NETEQTEST_RTPpacket::markerBit() const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000410{
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000411 if(_datagram && _datagramLen >= _kBasicHeaderLen)
412 {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000413 webrtc::WebRtcRTPHeader tempRTPinfo;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000414 parseRTPheader(&tempRTPinfo);
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000415 return tempRTPinfo.header.markerBit;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000416 }
417 else
418 {
419 return 0;
420 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000421}
422
423
424
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000425int NETEQTEST_RTPpacket::setPayloadType(uint8_t pt)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000426{
427
428 if (_datagramLen < 12)
429 {
430 return -1;
431 }
432
433 if (!_rtpParsed)
434 {
435 _rtpInfo.header.payloadType = pt;
436 }
437
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000438 _datagram[1] = pt;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000439
440 return 0;
441
442}
443
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000444int NETEQTEST_RTPpacket::setSequenceNumber(uint16_t sn)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000445{
446
447 if (_datagramLen < 12)
448 {
449 return -1;
450 }
451
452 if (!_rtpParsed)
453 {
454 _rtpInfo.header.sequenceNumber = sn;
455 }
456
457 _datagram[2]=(unsigned char)((sn>>8)&0xFF);
458 _datagram[3]=(unsigned char)((sn)&0xFF);
459
460 return 0;
461
462}
463
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000464int NETEQTEST_RTPpacket::setTimeStamp(uint32_t ts)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000465{
466
467 if (_datagramLen < 12)
468 {
469 return -1;
470 }
471
472 if (!_rtpParsed)
473 {
474 _rtpInfo.header.timestamp = ts;
475 }
476
477 _datagram[4]=(unsigned char)((ts>>24)&0xFF);
478 _datagram[5]=(unsigned char)((ts>>16)&0xFF);
479 _datagram[6]=(unsigned char)((ts>>8)&0xFF);
480 _datagram[7]=(unsigned char)(ts & 0xFF);
481
482 return 0;
483
484}
485
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000486int NETEQTEST_RTPpacket::setSSRC(uint32_t ssrc)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000487{
488
489 if (_datagramLen < 12)
490 {
491 return -1;
492 }
493
494 if (!_rtpParsed)
495 {
496 _rtpInfo.header.ssrc = ssrc;
497 }
498
499 _datagram[8]=(unsigned char)((ssrc>>24)&0xFF);
500 _datagram[9]=(unsigned char)((ssrc>>16)&0xFF);
501 _datagram[10]=(unsigned char)((ssrc>>8)&0xFF);
502 _datagram[11]=(unsigned char)(ssrc & 0xFF);
503
504 return 0;
505
506}
507
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000508int NETEQTEST_RTPpacket::setMarkerBit(uint8_t mb)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000509{
510
511 if (_datagramLen < 12)
512 {
513 return -1;
514 }
515
516 if (_rtpParsed)
517 {
518 _rtpInfo.header.markerBit = mb;
519 }
520
521 if (mb)
522 {
523 _datagram[0] |= 0x01;
524 }
525 else
526 {
527 _datagram[0] &= 0xFE;
528 }
529
530 return 0;
531
532}
533
534int NETEQTEST_RTPpacket::setRTPheader(const webrtc::WebRtcRTPHeader* RTPinfo)
535{
536 if (_datagramLen < 12)
537 {
538 // this packet is not ok
539 return -1;
540 }
541
542 makeRTPheader(_datagram,
543 RTPinfo->header.payloadType,
544 RTPinfo->header.sequenceNumber,
545 RTPinfo->header.timestamp,
546 RTPinfo->header.ssrc,
547 RTPinfo->header.markerBit);
548
549 return 0;
550}
551
552
553int NETEQTEST_RTPpacket::splitStereo(NETEQTEST_RTPpacket* slaveRtp,
554 enum stereoModes mode)
555{
556 // if mono, do nothing
557 if (mode == stereoModeMono)
558 {
559 return 0;
560 }
561
562 // check that the RTP header info is parsed
563 parseHeader();
564
565 // start by copying the main rtp packet
566 *slaveRtp = *this;
567
568 if(_payloadLen == 0)
569 {
570 // do no more
571 return 0;
572 }
573
574 if(_payloadLen%2 != 0)
575 {
576 // length must be a factor of 2
577 return -1;
578 }
579
580 switch(mode)
581 {
582 case stereoModeSample1:
583 {
584 // sample based codec with 1-byte samples
585 splitStereoSample(slaveRtp, 1 /* 1 byte/sample */);
586 break;
587 }
588 case stereoModeSample2:
589 {
590 // sample based codec with 2-byte samples
591 splitStereoSample(slaveRtp, 2 /* 2 bytes/sample */);
592 break;
593 }
594 case stereoModeFrame:
595 {
596 // frame based codec
597 splitStereoFrame(slaveRtp);
598 break;
599 }
600 case stereoModeDuplicate:
601 {
602 // frame based codec, send the whole packet to both master and slave
603 splitStereoDouble(slaveRtp);
604 break;
605 }
606 case stereoModeMono:
607 {
608 assert(false);
609 return -1;
610 }
611 }
612
613 return 0;
614}
615
616
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000617void NETEQTEST_RTPpacket::makeRTPheader(unsigned char* rtp_data,
618 uint8_t payloadType,
619 uint16_t seqNo,
620 uint32_t timestamp,
621 uint32_t ssrc,
622 uint8_t markerBit) const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000623{
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000624 rtp_data[0] = markerBit ? 0x81 : 0x80;
625 rtp_data[1] = payloadType;
626 rtp_data[2] = seqNo >> 8;
627 rtp_data[3] = seqNo & 0xFF;
628 rtp_data[4] = timestamp >> 24;
629 rtp_data[5] = (timestamp >> 16) & 0xFF;
630 rtp_data[6] = (timestamp >> 8) & 0xFF;
631 rtp_data[7] = timestamp & 0xFF;
632 rtp_data[8] = ssrc >> 24;
633 rtp_data[9] = (ssrc >> 16) & 0xFF;
634 rtp_data[10] = (ssrc >> 8) & 0xFF;
635 rtp_data[11] = ssrc & 0xFF;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000636}
637
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000638uint16_t NETEQTEST_RTPpacket::parseRTPheader(webrtc::WebRtcRTPHeader* RTPinfo,
639 uint8_t **payloadPtr) const
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000640{
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000641 uint16_t* rtp_data = reinterpret_cast<uint16_t*>(_datagram);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000642 int i_P, i_X, i_CC;
643
644 assert(_datagramLen >= 12);
645 parseBasicHeader(RTPinfo, &i_P, &i_X, &i_CC);
646
647 int i_startPosition = calcHeaderLength(i_X, i_CC);
648
649 int i_padlength = calcPadLength(i_P);
650
651 if (payloadPtr)
652 {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000653 *payloadPtr =
654 reinterpret_cast<uint8_t*>(&rtp_data[i_startPosition >> 1]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000655 }
656
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000657 return static_cast<uint16_t>(_datagramLen - i_startPosition - i_padlength);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000658}
659
660
661void NETEQTEST_RTPpacket::parseBasicHeader(webrtc::WebRtcRTPHeader* RTPinfo,
662 int *i_P, int *i_X, int *i_CC) const
663{
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000664 uint16_t* rtp_data = reinterpret_cast<uint16_t*>(_datagram);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000665 if (_datagramLen < 12)
666 {
667 assert(false);
668 return;
669 }
670
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000671 *i_P = (rtp_data[0] >> 5) & 0x01;
672 *i_X = (rtp_data[0] >> 4) & 0x01;
673 *i_CC = rtp_data[0] & 0xF;
674 RTPinfo->header.markerBit = (rtp_data[0] >> 15) & 0x01;
675 RTPinfo->header.payloadType = (rtp_data[0] >> 8) & 0x7F;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000676 RTPinfo->header.sequenceNumber =
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000677 (rtp_data[1] >> 8) | ((rtp_data[1] & 0xFF) << 8);
678 RTPinfo->header.timestamp =
679 ((rtp_data[2] & 0xFF) << 24) | ((rtp_data[2] & 0xFF00) << 8) |
680 (rtp_data[3] >> 8) | ((rtp_data[3] & 0xFF) << 8);
681 RTPinfo->header.ssrc =
682 ((rtp_data[4] & 0xFF) << 24) | ((rtp_data[4] & 0xFF00) << 8) |
683 (rtp_data[5] >> 8) | ((rtp_data[5] & 0xFF) << 8);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000684}
685
686int NETEQTEST_RTPpacket::calcHeaderLength(int i_X, int i_CC) const
687{
688 int i_extlength = 0;
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000689 uint16_t* rtp_data = reinterpret_cast<uint16_t*>(_datagram);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000690
691 if (i_X == 1)
692 {
693 // Extension header exists.
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000694 // Find out how many int32_t it consists of.
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000695 int offset = 7 + 2 * i_CC;
696 assert(_datagramLen > 2 * offset);
697 if (_datagramLen > 2 * offset)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000698 {
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000699 i_extlength = 1 +
700 (((rtp_data[offset]) >> 8) | ((rtp_data[offset] & 0xFF) << 8));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000701 }
702 }
703
704 return 12 + 4 * i_extlength + 4 * i_CC;
705}
706
707int NETEQTEST_RTPpacket::calcPadLength(int i_P) const
708{
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000709 uint16_t* rtp_data = reinterpret_cast<uint16_t*>(_datagram);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000710 if (i_P == 1)
711 {
712 /* Padding exists. Find out how many bytes the padding consists of. */
713 if (_datagramLen & 0x1)
714 {
715 /* odd number of bytes => last byte in higher byte */
716 return rtp_data[_datagramLen >> 1] & 0xFF;
717 }
718 else
719 {
720 /* even number of bytes => last byte in lower byte */
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000721 return rtp_data[(_datagramLen >> 1) - 1] >> 8;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000722 }
723 }
724 return 0;
725}
726
727void NETEQTEST_RTPpacket::splitStereoSample(NETEQTEST_RTPpacket* slaveRtp,
728 int stride)
729{
730 if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000731 || _payloadLen == 0 || slaveRtp->_memSize < _memSize)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000732 {
733 return;
734 }
735
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000736 uint8_t *readDataPtr = _payloadPtr;
737 uint8_t *writeDataPtr = _payloadPtr;
738 uint8_t *slaveData = slaveRtp->_payloadPtr;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000739
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000740 while (readDataPtr - _payloadPtr < static_cast<ptrdiff_t>(_payloadLen))
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000741 {
742 // master data
743 for (int ix = 0; ix < stride; ix++) {
744 *writeDataPtr = *readDataPtr;
745 writeDataPtr++;
746 readDataPtr++;
747 }
748
749 // slave data
750 for (int ix = 0; ix < stride; ix++) {
751 *slaveData = *readDataPtr;
752 slaveData++;
753 readDataPtr++;
754 }
755 }
756
757 _payloadLen /= 2;
758 slaveRtp->_payloadLen = _payloadLen;
759}
760
761
762void NETEQTEST_RTPpacket::splitStereoFrame(NETEQTEST_RTPpacket* slaveRtp)
763{
764 if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000765 || _payloadLen == 0 || slaveRtp->_memSize < _memSize)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000766 {
767 return;
768 }
769
770 memmove(slaveRtp->_payloadPtr, _payloadPtr + _payloadLen/2, _payloadLen/2);
771
772 _payloadLen /= 2;
773 slaveRtp->_payloadLen = _payloadLen;
774}
775void NETEQTEST_RTPpacket::splitStereoDouble(NETEQTEST_RTPpacket* slaveRtp)
776{
777 if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000778 || _payloadLen == 0 || slaveRtp->_memSize < _memSize)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000779 {
780 return;
781 }
782
783 memcpy(slaveRtp->_payloadPtr, _payloadPtr, _payloadLen);
784 slaveRtp->_payloadLen = _payloadLen;
785}
786
787// Get the RTP header for the RED payload indicated by argument index.
788// The first RED payload is index = 0.
789int NETEQTEST_RTPpacket::extractRED(int index, webrtc::WebRtcRTPHeader& red)
790{
791//
792// 0 1 2 3
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 4 5 6 7 8 9 0 1
794// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
795// |1| block PT | timestamp offset | block length |
796// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
797// |1| ... |
798// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
799// |0| block PT |
800// +-+-+-+-+-+-+-+-+
801//
802
803 parseHeader();
804
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000805 uint8_t* ptr = payload();
806 uint8_t* payloadEndPtr = ptr + payloadLen();
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000807 int num_encodings = 0;
808 int total_len = 0;
809
810 while ((ptr < payloadEndPtr) && (*ptr & 0x80))
811 {
812 int len = ((ptr[2] & 0x03) << 8) + ptr[3];
813 if (num_encodings == index)
814 {
815 // Header found.
816 red.header.payloadType = ptr[0] & 0x7F;
pkasting@chromium.orgd3245462015-02-23 21:28:22 +0000817 uint32_t offset = (ptr[1] << 6) + (ptr[2] >> 2);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000818 red.header.sequenceNumber = sequenceNumber();
819 red.header.timestamp = timeStamp() - offset;
820 red.header.markerBit = markerBit();
821 red.header.ssrc = SSRC();
822 return len;
823 }
824 ++num_encodings;
825 total_len += len;
826 ptr += 4;
827 }
828 if ((ptr < payloadEndPtr) && (num_encodings == index))
829 {
830 // Last header.
831 red.header.payloadType = ptr[0] & 0x7F;
832 red.header.sequenceNumber = sequenceNumber();
833 red.header.timestamp = timeStamp();
834 red.header.markerBit = markerBit();
835 red.header.ssrc = SSRC();
836 ++ptr;
837 return payloadLen() - (ptr - payload()) - total_len;
838 }
839 return -1;
840}
841
842// Randomize the payload, not the RTP header.
843void NETEQTEST_RTPpacket::scramblePayload(void)
844{
845 parseHeader();
846
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000847 for (size_t i = 0; i < _payloadLen; ++i)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000848 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000849 _payloadPtr[i] = static_cast<uint8_t>(rand());
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000850 }
851}