• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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