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 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 41 NETEQTEST_RTPpacket::~NETEQTEST_RTPpacket() 42 { 43 if(_datagram) 44 { 45 delete [] _datagram; 46 } 47 } 48 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 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 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 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 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 255 void NETEQTEST_RTPpacket::blockPT(uint8_t pt) 256 { 257 _blockList[pt] = true; 258 } 259 260 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 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 296 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 308 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 320 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 332 size_t NETEQTEST_RTPpacket::payloadLen() 333 { 334 parseHeader(); 335 return _payloadLen; 336 } 337 338 int16_t NETEQTEST_RTPpacket::dataLen() const 339 { 340 return _datagramLen; 341 } 342 343 bool NETEQTEST_RTPpacket::isParsed() const 344 { 345 return _rtpParsed; 346 } 347 348 bool NETEQTEST_RTPpacket::isLost() const 349 { 350 return _lost; 351 } 352 353 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 367 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 381 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 395 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 409 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 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 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 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 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 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 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 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 617 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 638 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 661 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 686 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 707 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 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 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 } 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. 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. 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