1 /*
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
23 const int NETEQTEST_RTPpacket::_kRDHeaderLen = 8;
24 const int NETEQTEST_RTPpacket::_kBasicHeaderLen = 12;
25
NETEQTEST_RTPpacket()26 NETEQTEST_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
~NETEQTEST_RTPpacket()41 NETEQTEST_RTPpacket::~NETEQTEST_RTPpacket()
42 {
43 if(_datagram)
44 {
45 delete [] _datagram;
46 }
47 }
48
reset()49 void 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
skipFileHeader(FILE * fp)65 int 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
readFromFile(FILE * fp)99 int NETEQTEST_RTPpacket::readFromFile(FILE *fp)
100 {
101 if(!fp)
102 {
103 return(-1);
104 }
105
106 uint16_t length, plen;
107 uint32_t offset;
108 int packetLen = 0;
109
110 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);
119
120 if (fread(&plen,2,1,fp)==0)
121 {
122 reset();
123 return(-1);
124 }
125 packetLen = ntohs(plen);
126
127 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);
134
135 // Use length here because a plen of 0 specifies rtcp
136 length = (uint16_t) (length - _kRDHeaderLen);
137
138 // check buffer size
139 if (_datagram && _memSize < length)
140 {
141 reset();
142 }
143
144 if (!_datagram)
145 {
146 _datagram = new uint8_t[length];
147 _memSize = length;
148 }
149
150 if (fread((unsigned short *) _datagram,1,length,fp) != length)
151 {
152 reset();
153 return(-1);
154 }
155
156 _datagramLen = length;
157 _receiveTime = receiveTime;
158
159 if (!_blockList.empty() && _blockList.count(payloadType()) > 0)
160 {
161 readNextPacket = true;
162 }
163 }
164
165 _rtpParsed = false;
166 return(packetLen);
167
168 }
169
170
readFixedFromFile(FILE * fp,size_t length)171 int 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 {
186 _datagram = new uint8_t[length];
187 _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
writeToFile(FILE * fp)211 int NETEQTEST_RTPpacket::writeToFile(FILE *fp)
212 {
213 if (!fp)
214 {
215 return -1;
216 }
217
218 uint16_t length, plen;
219 uint32_t offset;
220
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
blockPT(uint8_t pt)255 void NETEQTEST_RTPpacket::blockPT(uint8_t pt)
256 {
257 _blockList[pt] = true;
258 }
259
260
parseHeader()261 void 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
parseHeader(webrtc::WebRtcRTPHeader * rtp_header)283 void 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
RTPinfo() const296 const webrtc::WebRtcRTPHeader* NETEQTEST_RTPpacket::RTPinfo() const
297 {
298 if (_rtpParsed)
299 {
300 return &_rtpInfo;
301 }
302 else
303 {
304 return NULL;
305 }
306 }
307
datagram() const308 uint8_t * NETEQTEST_RTPpacket::datagram() const
309 {
310 if (_datagramLen > 0)
311 {
312 return _datagram;
313 }
314 else
315 {
316 return NULL;
317 }
318 }
319
payload() const320 uint8_t * NETEQTEST_RTPpacket::payload() const
321 {
322 if (_payloadLen > 0)
323 {
324 return _payloadPtr;
325 }
326 else
327 {
328 return NULL;
329 }
330 }
331
payloadLen()332 size_t NETEQTEST_RTPpacket::payloadLen()
333 {
334 parseHeader();
335 return _payloadLen;
336 }
337
dataLen() const338 int16_t NETEQTEST_RTPpacket::dataLen() const
339 {
340 return _datagramLen;
341 }
342
isParsed() const343 bool NETEQTEST_RTPpacket::isParsed() const
344 {
345 return _rtpParsed;
346 }
347
isLost() const348 bool NETEQTEST_RTPpacket::isLost() const
349 {
350 return _lost;
351 }
352
payloadType() const353 uint8_t NETEQTEST_RTPpacket::payloadType() const
354 {
355 if(_datagram && _datagramLen >= _kBasicHeaderLen)
356 {
357 webrtc::WebRtcRTPHeader tempRTPinfo;
358 parseRTPheader(&tempRTPinfo);
359 return tempRTPinfo.header.payloadType;
360 }
361 else
362 {
363 return 0;
364 }
365 }
366
sequenceNumber() const367 uint16_t NETEQTEST_RTPpacket::sequenceNumber() const
368 {
369 if(_datagram && _datagramLen >= _kBasicHeaderLen)
370 {
371 webrtc::WebRtcRTPHeader tempRTPinfo;
372 parseRTPheader(&tempRTPinfo);
373 return tempRTPinfo.header.sequenceNumber;
374 }
375 else
376 {
377 return 0;
378 }
379 }
380
timeStamp() const381 uint32_t NETEQTEST_RTPpacket::timeStamp() const
382 {
383 if(_datagram && _datagramLen >= _kBasicHeaderLen)
384 {
385 webrtc::WebRtcRTPHeader tempRTPinfo;
386 parseRTPheader(&tempRTPinfo);
387 return tempRTPinfo.header.timestamp;
388 }
389 else
390 {
391 return 0;
392 }
393 }
394
SSRC() const395 uint32_t NETEQTEST_RTPpacket::SSRC() const
396 {
397 if(_datagram && _datagramLen >= _kBasicHeaderLen)
398 {
399 webrtc::WebRtcRTPHeader tempRTPinfo;
400 parseRTPheader(&tempRTPinfo);
401 return tempRTPinfo.header.ssrc;
402 }
403 else
404 {
405 return 0;
406 }
407 }
408
markerBit() const409 uint8_t NETEQTEST_RTPpacket::markerBit() const
410 {
411 if(_datagram && _datagramLen >= _kBasicHeaderLen)
412 {
413 webrtc::WebRtcRTPHeader tempRTPinfo;
414 parseRTPheader(&tempRTPinfo);
415 return tempRTPinfo.header.markerBit;
416 }
417 else
418 {
419 return 0;
420 }
421 }
422
423
424
setPayloadType(uint8_t pt)425 int NETEQTEST_RTPpacket::setPayloadType(uint8_t pt)
426 {
427
428 if (_datagramLen < 12)
429 {
430 return -1;
431 }
432
433 if (!_rtpParsed)
434 {
435 _rtpInfo.header.payloadType = pt;
436 }
437
438 _datagram[1] = pt;
439
440 return 0;
441
442 }
443
setSequenceNumber(uint16_t sn)444 int NETEQTEST_RTPpacket::setSequenceNumber(uint16_t sn)
445 {
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
setTimeStamp(uint32_t ts)464 int NETEQTEST_RTPpacket::setTimeStamp(uint32_t ts)
465 {
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
setSSRC(uint32_t ssrc)486 int NETEQTEST_RTPpacket::setSSRC(uint32_t ssrc)
487 {
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
setMarkerBit(uint8_t mb)508 int NETEQTEST_RTPpacket::setMarkerBit(uint8_t mb)
509 {
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
setRTPheader(const webrtc::WebRtcRTPHeader * RTPinfo)534 int 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
splitStereo(NETEQTEST_RTPpacket * slaveRtp,enum stereoModes mode)553 int 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
makeRTPheader(unsigned char * rtp_data,uint8_t payloadType,uint16_t seqNo,uint32_t timestamp,uint32_t ssrc,uint8_t markerBit) const617 void 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
623 {
624 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;
636 }
637
parseRTPheader(webrtc::WebRtcRTPHeader * RTPinfo,uint8_t ** payloadPtr) const638 uint16_t NETEQTEST_RTPpacket::parseRTPheader(webrtc::WebRtcRTPHeader* RTPinfo,
639 uint8_t **payloadPtr) const
640 {
641 uint16_t* rtp_data = reinterpret_cast<uint16_t*>(_datagram);
642 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 {
653 *payloadPtr =
654 reinterpret_cast<uint8_t*>(&rtp_data[i_startPosition >> 1]);
655 }
656
657 return static_cast<uint16_t>(_datagramLen - i_startPosition - i_padlength);
658 }
659
660
parseBasicHeader(webrtc::WebRtcRTPHeader * RTPinfo,int * i_P,int * i_X,int * i_CC) const661 void NETEQTEST_RTPpacket::parseBasicHeader(webrtc::WebRtcRTPHeader* RTPinfo,
662 int *i_P, int *i_X, int *i_CC) const
663 {
664 uint16_t* rtp_data = reinterpret_cast<uint16_t*>(_datagram);
665 if (_datagramLen < 12)
666 {
667 assert(false);
668 return;
669 }
670
671 *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;
676 RTPinfo->header.sequenceNumber =
677 (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);
684 }
685
calcHeaderLength(int i_X,int i_CC) const686 int NETEQTEST_RTPpacket::calcHeaderLength(int i_X, int i_CC) const
687 {
688 int i_extlength = 0;
689 uint16_t* rtp_data = reinterpret_cast<uint16_t*>(_datagram);
690
691 if (i_X == 1)
692 {
693 // Extension header exists.
694 // Find out how many int32_t it consists of.
695 int offset = 7 + 2 * i_CC;
696 assert(_datagramLen > 2 * offset);
697 if (_datagramLen > 2 * offset)
698 {
699 i_extlength = 1 +
700 (((rtp_data[offset]) >> 8) | ((rtp_data[offset] & 0xFF) << 8));
701 }
702 }
703
704 return 12 + 4 * i_extlength + 4 * i_CC;
705 }
706
calcPadLength(int i_P) const707 int NETEQTEST_RTPpacket::calcPadLength(int i_P) const
708 {
709 uint16_t* rtp_data = reinterpret_cast<uint16_t*>(_datagram);
710 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 */
721 return rtp_data[(_datagramLen >> 1) - 1] >> 8;
722 }
723 }
724 return 0;
725 }
726
splitStereoSample(NETEQTEST_RTPpacket * slaveRtp,int stride)727 void NETEQTEST_RTPpacket::splitStereoSample(NETEQTEST_RTPpacket* slaveRtp,
728 int stride)
729 {
730 if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
731 || _payloadLen == 0 || slaveRtp->_memSize < _memSize)
732 {
733 return;
734 }
735
736 uint8_t *readDataPtr = _payloadPtr;
737 uint8_t *writeDataPtr = _payloadPtr;
738 uint8_t *slaveData = slaveRtp->_payloadPtr;
739
740 while (readDataPtr - _payloadPtr < static_cast<ptrdiff_t>(_payloadLen))
741 {
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
splitStereoFrame(NETEQTEST_RTPpacket * slaveRtp)762 void NETEQTEST_RTPpacket::splitStereoFrame(NETEQTEST_RTPpacket* slaveRtp)
763 {
764 if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
765 || _payloadLen == 0 || slaveRtp->_memSize < _memSize)
766 {
767 return;
768 }
769
770 memmove(slaveRtp->_payloadPtr, _payloadPtr + _payloadLen/2, _payloadLen/2);
771
772 _payloadLen /= 2;
773 slaveRtp->_payloadLen = _payloadLen;
774 }
splitStereoDouble(NETEQTEST_RTPpacket * slaveRtp)775 void NETEQTEST_RTPpacket::splitStereoDouble(NETEQTEST_RTPpacket* slaveRtp)
776 {
777 if(!_payloadPtr || !slaveRtp || !slaveRtp->_payloadPtr
778 || _payloadLen == 0 || slaveRtp->_memSize < _memSize)
779 {
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.
extractRED(int index,webrtc::WebRtcRTPHeader & red)789 int 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
805 uint8_t* ptr = payload();
806 uint8_t* payloadEndPtr = ptr + payloadLen();
807 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;
817 uint32_t offset = (ptr[1] << 6) + (ptr[2] >> 2);
818 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.
scramblePayload(void)843 void NETEQTEST_RTPpacket::scramblePayload(void)
844 {
845 parseHeader();
846
847 for (size_t i = 0; i < _payloadLen; ++i)
848 {
849 _payloadPtr[i] = static_cast<uint8_t>(rand());
850 }
851 }
852