1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 /* */ 19 /*********************************************************************************/ 20 21 /* 22 ** File: rtcp_decoder.cpp 23 ** 24 ** Description: 25 ** This module implements the RTCP_Decoder class. This class is used to encode and 26 ** decode RTCP_Decoder packets. Please refer to the RTCP_Decoder design document for 27 ** details. 28 */ 29 30 /* 31 ** Includes 32 */ 33 34 35 #define DEBUG_PRINT 0 36 #if DEBUG_PRINT 37 #include <stdio.h> 38 #endif 39 40 #ifdef PV_OS_ZREX 41 //you get a compile error on zrex for the arm target 42 //unless these includes come first. 43 #include <stdlib.h> 44 #include <math.h> 45 #endif 46 47 #include "rtcp_decoder.h" 48 #include "rtcp_constants.h" 49 #include "oscl_mem.h" 50 51 /* 52 ** Constants 53 */ 54 55 /* 56 ** Methods 57 */ 58 OSCL_EXPORT_REF RTCP_Decoder::RTCP_Decoder(const uint8 version) 59 : RTCP_Base(version) 60 { 61 62 } 63 64 OSCL_EXPORT_REF RTCP_Decoder::~RTCP_Decoder() 65 { 66 } 67 68 OSCL_EXPORT_REF RTCP_Decoder::Error_t 69 RTCP_Decoder::scan_compound_packet(OsclMemoryFragment& input_packet, 70 int32 max_array_size, int32& filled_size, 71 RTCPPacketType *array_of_packet_types, 72 OsclMemoryFragment *array_of_packets) 73 { 74 75 uint8 *ptr = (uint8 *) input_packet.ptr; 76 int32 remaining_len = input_packet.len; 77 78 filled_size = 0; 79 80 if (! ptr || remaining_len <= 0) 81 { 82 return FAIL; 83 } 84 85 OsclBinIStreamBigEndian inStream; 86 inStream.Attach(ptr, remaining_len); 87 uint8 tempChar; 88 89 while (remaining_len > 0 && filled_size < max_array_size) 90 { 91 92 inStream >> tempChar; 93 if (inStream.fail()) 94 { 95 return EOS_ON_READ; 96 } 97 98 // read the type 99 uint8 payloadType; 100 uint16 rtcpLength; 101 inStream >> payloadType; 102 inStream >> rtcpLength; 103 if (inStream.fail()) 104 { 105 return EOS_ON_READ; 106 } 107 108 // store the length and type 109 switch (payloadType) 110 { 111 112 case SR_PACKET_TYPE: 113 array_of_packet_types[filled_size] = SR_RTCP_PACKET; 114 break; 115 116 case RR_PACKET_TYPE: 117 array_of_packet_types[filled_size] = RR_RTCP_PACKET; 118 break; 119 120 case SDES_PACKET_TYPE: 121 array_of_packet_types[filled_size] = SDES_RTCP_PACKET; 122 break; 123 124 case BYE_PACKET_TYPE: 125 array_of_packet_types[filled_size] = BYE_RTCP_PACKET; 126 break; 127 128 case APP_PACKET_TYPE: 129 { 130 // figure out whether this is a PVSS type 131 // ptr is at the beginning of APP packet 132 uint8* test_ptr = ptr + 8; 133 if (oscl_memcmp(test_ptr, PVSS_APP_RTCP_NAME, 4)) 134 { 135 array_of_packet_types[filled_size] = APP_RTCP_PACKET; 136 } 137 else 138 { 139 array_of_packet_types[filled_size] = PVSS_APP_RTCP_PACKET; 140 } 141 break; 142 } 143 144 145 default: 146 array_of_packet_types[filled_size] = UNKNOWN_RTCP_PACKET; 147 break; 148 } 149 150 // record the ptr and length 151 array_of_packets[filled_size].ptr = ptr; 152 array_of_packets[filled_size++].len = (rtcpLength + 1) * 4; 153 154 remaining_len -= (rtcpLength + 1) * 4; 155 156 ptr += (rtcpLength + 1) * 4; 157 if (rtcpLength) 158 { 159 inStream.seekFromCurrentPosition((rtcpLength*4)); 160 if (inStream.fail()) 161 { 162 return EOS_ON_READ; 163 } 164 } 165 166 } // end while loop 167 168 169 return RTCP_SUCCESS; 170 171 } 172 173 174 175 176 // Start of new code 177 178 /* 179 ** Description: 180 ** Decode a sender or receiver report block 181 ** 182 ** Returns: SUCCESS if successful, FAIL if not. 183 ** Side effects: None. 184 */ 185 RTCP_Decoder::Error_t RTCP_Decoder::DecodeReportBlock( 186 OsclBinIStreamBigEndian & inStream, /* Input stream reference */ 187 RTCP_ReportBlock* report 188 ) 189 { 190 if (! report) 191 { 192 return FAIL; 193 } 194 195 inStream >> report->sourceSSRC; 196 const uint32 SIGN_BIT_MASK = 0x800000; 197 const uint32 SIGN_EXTENSION = 0xFF000000; 198 199 uint32 tempint32; 200 inStream >> tempint32; 201 report->fractionLost = (uint8)(tempint32 >> FRACTION_LOST_POSITION); 202 report->cumulativeNumberOfPacketsLost = tempint32 & FRACTION_LOST_MASK; 203 if (report->cumulativeNumberOfPacketsLost & SIGN_BIT_MASK) 204 { 205 report->cumulativeNumberOfPacketsLost |= SIGN_EXTENSION; 206 } 207 208 inStream >> report->highestSequenceNumberReceived; 209 inStream >> report->interarrivalJitter; 210 211 inStream >> report->lastSR; 212 inStream >> report->delaySinceLastSR; 213 214 if (inStream.fail()) 215 { 216 return FAIL; 217 } 218 else 219 { 220 return RTCP_SUCCESS; 221 } 222 } 223 224 225 226 OSCL_EXPORT_REF RTCP_Decoder::Error_t 227 RTCP_Decoder::DecodeRR(OsclMemoryFragment& input_packet, 228 RTCP_RR& rr_packet) 229 { 230 231 #if DEBUG_PRINT 232 printf("Within RTCP_Decoder::DecodeRR\n"); 233 #endif 234 235 // attach the bin stream 236 OsclBinIStreamBigEndian inStream; 237 238 if (input_packet.ptr == NULL || 239 input_packet.len == 0) 240 { 241 return FAIL; 242 } 243 244 inStream.Attach(input_packet.ptr, input_packet.len); 245 uint8 tempChar; 246 247 // decode the version, report count, packet type, and length 248 inStream >> tempChar; 249 if (inStream.eof() || inStream.fail()) 250 { 251 return FAIL; 252 } 253 254 uint8 rcvdVersion = tempChar >> RTPRTCP_VERSION_BIT_POSITION; 255 uint8 report_count = tempChar & RECORD_COUNT_MASK; 256 if (rcvdVersion != rtcpVersion) 257 { 258 #if DEBUG_PRINT 259 printf("Wrong RR RTP version\n"); 260 #endif 261 return UNSUPPORTED_RTCP_VERSION; 262 } 263 264 uint8 payloadType; 265 uint16 rtcpLength; 266 inStream >> payloadType; 267 inStream >> rtcpLength; 268 if (inStream.fail()) 269 { 270 return FAIL; 271 } 272 273 if (payloadType != RR_PACKET_TYPE) 274 { 275 return RTCP_PACKET_TYPE_MISMATCH; 276 } 277 278 if (rtcpLength < (report_count*6 + 1)) 279 { 280 return RTCP_LENGTH_MISMATCH; 281 } 282 283 // set the number of report blocks 284 rr_packet.set_max_report_blocks(report_count); 285 286 // decode the sender SSRC 287 inStream >> rr_packet.senderSSRC; 288 289 Error_t status; 290 // decode each of the report blocks 291 for (uint ii = 0; ii < report_count; ++ii) 292 { 293 if ((status = DecodeReportBlock(inStream, rr_packet.get_report_block(ii))) != RTCP_SUCCESS) 294 { 295 return status; 296 } 297 } 298 299 return RTCP_SUCCESS; 300 } 301 302 /* 303 ** Description: 304 ** Decode a SR (sender report) RTCP_Decoder object. 305 ** 306 ** Returns: SUCCESS if successful, FAIL if not. 307 ** Side effects: None. 308 */ 309 OSCL_EXPORT_REF RTCP_Decoder::Error_t RTCP_Decoder::DecodeSR( 310 const OsclMemoryFragment& input_packet, 311 RTCP_SR& sr_packet) 312 { 313 314 #if DEBUG_PRINT 315 printf("Within RTCP_Decoder::DecodeSR\n"); 316 #endif 317 318 // attach the bin stream 319 OsclBinIStreamBigEndian inStream; 320 321 if (input_packet.ptr == NULL || 322 input_packet.len == 0) 323 { 324 return FAIL; 325 } 326 327 inStream.Attach(input_packet.ptr, input_packet.len); 328 uint8 tempChar; 329 330 // decode the version, report count, packet type, and length 331 inStream >> tempChar; 332 if (inStream.eof() || inStream.fail()) 333 { 334 return FAIL; 335 } 336 337 uint8 rcvdVersion = tempChar >> RTPRTCP_VERSION_BIT_POSITION; 338 uint8 report_count = tempChar & RECORD_COUNT_MASK; 339 if (rcvdVersion != rtcpVersion) 340 { 341 #if DEBUG_PRINT 342 printf("Wrong SR RTCP version\n"); 343 #endif 344 return UNSUPPORTED_RTCP_VERSION; 345 } 346 347 // set the max report 348 349 350 uint8 payloadType; 351 uint16 rtcpLength; 352 inStream >> payloadType; 353 inStream >> rtcpLength; 354 if (inStream.fail()) 355 { 356 return FAIL; 357 } 358 359 if (payloadType != SR_PACKET_TYPE) 360 { 361 return RTCP_PACKET_TYPE_MISMATCH; 362 } 363 364 if (rtcpLength < (report_count*6 + 6)) 365 { 366 return RTCP_LENGTH_MISMATCH; 367 } 368 369 // read the sender information 370 // decode the sender SSRC 371 inStream >> sr_packet.senderSSRC; 372 inStream >> sr_packet.NTP_timestamp_high; 373 inStream >> sr_packet.NTP_timestamp_low; 374 inStream >> sr_packet.RTP_timestamp; 375 inStream >> sr_packet.packet_count; 376 inStream >> sr_packet.octet_count; 377 378 if (inStream.fail()) 379 { 380 return FAIL; 381 } 382 383 // set the number of report blocks 384 sr_packet.set_max_report_blocks(report_count); 385 386 387 Error_t status; 388 // decode each of the report blocks 389 for (uint ii = 0; ii < report_count; ++ii) 390 { 391 if ((status = DecodeReportBlock(inStream, sr_packet.get_report_block(ii))) != RTCP_SUCCESS) 392 { 393 return status; 394 } 395 } 396 397 return RTCP_SUCCESS; 398 } 399 400 401 /* 402 ** Description: 403 ** Decode a SDES RTCP_Decoder object. The only field supported and encoded is CNAME. 404 ** 405 ** Returns: SUCCESS if successful, FAIL if not. 406 ** Side effects: None. 407 */ 408 OSCL_EXPORT_REF RTCP_Decoder::Error_t 409 RTCP_Decoder::DecodeSDES( 410 const OsclMemoryFragment& input_packet, 411 RTCP_SDES& sdes_packet) 412 { 413 414 // attach the bin stream 415 OsclBinIStreamBigEndian inStream; 416 417 if (input_packet.ptr == NULL || 418 input_packet.len == 0) 419 { 420 return FAIL; 421 } 422 423 inStream.Attach(input_packet.ptr, input_packet.len); 424 uint8 tempChar; 425 426 // decode the version, report count, packet type, and length 427 inStream >> tempChar; 428 if (inStream.eof() || inStream.fail()) 429 { 430 return FAIL; 431 } 432 433 uint8 rcvdVersion = tempChar >> RTPRTCP_VERSION_BIT_POSITION; 434 uint8 chunk_count = tempChar & RECORD_COUNT_MASK; 435 if (rcvdVersion != rtcpVersion) 436 { 437 #if DEBUG_PRINT 438 printf("Wrong RR RTP version\n"); 439 #endif 440 return UNSUPPORTED_RTCP_VERSION; 441 } 442 443 uint8 payloadType; 444 uint16 rtcpLength; 445 inStream >> payloadType; 446 inStream >> rtcpLength; 447 if (inStream.fail()) 448 { 449 return FAIL; 450 } 451 452 if (payloadType != SDES_PACKET_TYPE) 453 { 454 return RTCP_PACKET_TYPE_MISMATCH; 455 } 456 457 458 sdes_packet.set_max_chunks(chunk_count); 459 460 // now decode each chunk 461 SDES_chunk* chunk_ptr; 462 Error_t status; 463 OsclMemoryFragment chunk_frag; 464 for (uint ii = 0; ii < chunk_count; ++ii) 465 { 466 if (!(chunk_ptr = sdes_packet.get_chunk(ii))) 467 { 468 return FAIL; 469 } 470 chunk_frag.ptr = inStream.tellg() + ((int8*)input_packet.ptr); 471 chunk_frag.len = input_packet.len - inStream.tellg(); 472 if ((status = DecodeSDESChunk(inStream, chunk_ptr, chunk_frag)) != RTCP_SUCCESS) 473 { 474 return status; 475 } 476 } 477 478 return RTCP_SUCCESS; 479 480 } 481 482 483 RTCP_Decoder::Error_t 484 RTCP_Decoder::DecodeSDESChunk(OsclBinIStreamBigEndian & inStream, 485 SDES_chunk* sdes_chunk, 486 OsclMemoryFragment& chunk_data) 487 { 488 // create a temporary for up to TMP_SDES_STORAGE sdes items. 489 const uint TMP_SDES_STORAGE = 10; 490 491 if (! sdes_chunk) 492 { 493 return FAIL; 494 } 495 496 uint8* ptr = (uint8 *)chunk_data.ptr; 497 int32 len = chunk_data.len; 498 uint8* end_ptr = ptr + len; 499 500 SDES_item tmp_sdes_items[TMP_SDES_STORAGE]; 501 502 503 // get the ssrc 504 inStream >> sdes_chunk->ssrc; 505 len -= sizeof(sdes_chunk->ssrc); 506 ptr += sizeof(sdes_chunk->ssrc); 507 508 uint num_items = 0; 509 // figure out the number of sdes items 510 while ((ptr <= end_ptr - 2) && (*ptr != 0)) 511 { 512 if (num_items < TMP_SDES_STORAGE) 513 { 514 // store the information 515 tmp_sdes_items[num_items].type = *ptr++; 516 uint8 item_len = *ptr++; 517 len -= 2; 518 if (item_len > len) 519 { 520 return EOS_ON_READ; 521 } 522 tmp_sdes_items[num_items].content.ptr = ptr; 523 tmp_sdes_items[num_items].content.len = item_len; 524 ptr += item_len; 525 len -= item_len; 526 } 527 else 528 { 529 // simply skip over this one and count it. 530 ++ptr; 531 uint8 item_len = *ptr++; 532 len -= 2; 533 if (item_len > len) 534 { 535 return EOS_ON_READ; 536 } 537 ptr += item_len; 538 len -= item_len; 539 } 540 541 ++num_items; 542 } 543 544 if (*ptr != 0) 545 { 546 return EOS_ON_READ; 547 } 548 549 550 // set the max number of sdes items 551 sdes_chunk->set_max_items(num_items); 552 553 // record the tmp SDES items 554 uint loop_limit = (num_items <= TMP_SDES_STORAGE) ? num_items : TMP_SDES_STORAGE; 555 556 SDES_item* sdes_item_ptr; 557 uint ii; 558 for (ii = 0; ii < loop_limit; ++ii) 559 { 560 if (!(sdes_item_ptr = sdes_chunk->get_item(ii))) 561 { 562 return FAIL; 563 } 564 *sdes_item_ptr = tmp_sdes_items[ii]; 565 } 566 567 // record any remaining items beyond the temp storage size 568 if ((loop_limit < num_items) && (ii < TMP_SDES_STORAGE)) 569 { 570 uint8* cp_ptr = (uint8*) tmp_sdes_items[ii].content.ptr; 571 uint8 cp_len = (uint8)(tmp_sdes_items[ii].content.len & 0xFF); 572 573 cp_ptr += cp_len; 574 len = end_ptr - cp_ptr; 575 ii = loop_limit; 576 while ((ii < num_items) && (cp_ptr <= end_ptr - 2) && (*cp_ptr != 0)) 577 { 578 if (!(sdes_item_ptr = sdes_chunk->get_item(ii))) 579 { 580 return FAIL; 581 } 582 583 sdes_item_ptr->type = *cp_ptr++; 584 uint8 item_len = *cp_ptr++; 585 len -= 2; 586 if (item_len > len) 587 { 588 return EOS_ON_READ; 589 } 590 sdes_item_ptr->content.ptr = cp_ptr; 591 sdes_item_ptr->content.len = item_len; 592 cp_ptr += item_len; 593 len -= item_len; 594 ++ii; 595 } 596 597 } 598 599 // now skip over the padding 600 // subtract off the SSRC length (even though it is 601 len = ptr - sizeof(sdes_chunk->ssrc) - (uint8 *)chunk_data.ptr; 602 603 int32 pad_bytes = 4 - (len & 0x3); 604 605 // move the inStream pos ahead 606 inStream.seekFromCurrentPosition(len + pad_bytes); 607 608 if (inStream.fail()) 609 { 610 return FAIL; 611 } 612 613 return RTCP_SUCCESS; 614 615 } 616 617 618 /* 619 ** Description: 620 ** Decode a RTCP BYE report. 621 ** 622 ** Returns: SUCCESS if successful, FAIL if not. 623 ** Side effects: None. 624 */ 625 OSCL_EXPORT_REF RTCP_Decoder::Error_t 626 RTCP_Decoder::DecodeBYE(const OsclMemoryFragment& input_packet, 627 RTCP_BYE& bye_packet) 628 { 629 630 #if DEBUG_PRINT 631 printf("Within RTCP_Decoder::DecodeBYE\n"); 632 #endif 633 634 // attach the bin stream 635 OsclBinIStreamBigEndian inStream; 636 637 if (input_packet.ptr == NULL || 638 input_packet.len == 0) 639 { 640 return FAIL; 641 } 642 643 inStream.Attach(input_packet.ptr, input_packet.len); 644 uint8 tempChar; 645 646 // decode the version, report count, packet type, and length 647 inStream >> tempChar; 648 if (inStream.eof() || inStream.fail()) 649 { 650 return FAIL; 651 } 652 653 uint8 rcvdVersion = tempChar >> RTPRTCP_VERSION_BIT_POSITION; 654 uint8 sourceCount = tempChar & RECORD_COUNT_MASK; 655 if (rcvdVersion != rtcpVersion) 656 { 657 #if DEBUG_PRINT 658 printf("Wrong SR RTCP version\n"); 659 #endif 660 return UNSUPPORTED_RTCP_VERSION; 661 } 662 663 uint8 payloadType; 664 uint16 rtcpLength; 665 inStream >> payloadType; 666 inStream >> rtcpLength; 667 if (inStream.fail()) 668 { 669 return FAIL; 670 } 671 672 673 if (payloadType != BYE_PACKET_TYPE) 674 { 675 return RTCP_PACKET_TYPE_MISMATCH; 676 } 677 678 bye_packet.src_count = sourceCount; 679 for (uint ii = 0; ii < sourceCount; ++ii) 680 { 681 inStream >> bye_packet.ssrc_array[ii]; 682 if (inStream.fail()) 683 { 684 return FAIL; 685 } 686 } 687 688 // now check the reason string 689 int32 len = inStream.PositionInBlock(); 690 691 bye_packet.reason_string.ptr = 0; 692 bye_packet.reason_string.len = 0; 693 694 if (len < (rtcpLength + 1)*4) 695 { 696 uint8 tmplen; 697 inStream >> tmplen; 698 if (inStream.fail()) 699 { 700 return FAIL; 701 } 702 703 if (tmplen + len + 1 > (rtcpLength + 1)*4) 704 { 705 return EOS_ON_READ; 706 } 707 708 bye_packet.reason_string.ptr = ((uint8*) input_packet.ptr) + len + 1; 709 bye_packet.reason_string.len = tmplen; 710 711 } 712 713 return RTCP_SUCCESS; 714 } 715 716 /* 717 ** Description: 718 ** Decode a RTCP BYE report. 719 ** 720 ** Returns: SUCCESS if successful, FAIL if not. 721 ** Side effects: None. 722 */ 723 OSCL_EXPORT_REF RTCP_Decoder::Error_t RTCP_Decoder::DecodeAPP(const OsclMemoryFragment& input_packet, 724 RTCP_APP& app_packet) 725 { 726 727 // attach the bin stream 728 OsclBinIStreamBigEndian inStream; 729 730 if (input_packet.ptr == NULL || 731 input_packet.len == 0) 732 { 733 return FAIL; 734 } 735 736 inStream.Attach(input_packet.ptr, input_packet.len); 737 uint8 tempChar; 738 739 // decode the version, report count, packet type, and length 740 inStream >> tempChar; 741 if (inStream.eof() || inStream.fail()) 742 { 743 return FAIL; 744 } 745 746 uint8 rcvdVersion = tempChar >> RTPRTCP_VERSION_BIT_POSITION; 747 uint8 padBit = ((tempChar & (1 << RTPRTCP_PAD_FLAG_BIT_POSITION)) != 0); 748 uint8 subType = tempChar & RECORD_COUNT_MASK; 749 if (rcvdVersion != rtcpVersion) 750 { 751 #if DEBUG_PRINT 752 printf("Wrong SR RTCP version\n"); 753 #endif 754 return UNSUPPORTED_RTCP_VERSION; 755 } 756 757 uint8 payloadType; 758 uint16 rtcpLength; 759 inStream >> payloadType; 760 inStream >> rtcpLength; 761 if (inStream.fail()) 762 { 763 return FAIL; 764 } 765 766 767 if (payloadType != APP_PACKET_TYPE) 768 { 769 return RTCP_PACKET_TYPE_MISMATCH; 770 } 771 772 uint8* endPtr = (uint8*)input_packet.ptr + (rtcpLength + 1) * 4; 773 if (padBit) 774 { 775 uint8 pad_size = *(endPtr - 1); 776 endPtr -= pad_size; 777 // must at least be 12 characters 778 if (endPtr < (uint8*)input_packet.ptr + 12) 779 { 780 return FAIL; 781 } 782 } 783 784 785 inStream >> app_packet.ssrc; 786 inStream.get((int8 *) app_packet.type, 4); 787 if (inStream.fail()) 788 { 789 return FAIL; 790 } 791 792 793 app_packet.subtype = subType; 794 if (oscl_memcmp(app_packet.type, PVSS_APP_RTCP_NAME, 4)) 795 { 796 // some other app packet -- just record the memory ptr and length 797 app_packet.app_data.ptr = ((uint8*)input_packet.ptr) + inStream.tellg(); 798 app_packet.app_data.len = endPtr - ((uint8*)app_packet.app_data.ptr); 799 return RTCP_SUCCESS; 800 } 801 802 803 // store the subtype in the PVSS APP data structure also. 804 app_packet.pvss_app_data.subtype = subType; 805 806 // Check SubType 807 if (subType > RTCP_PVSS_APP_MAX_SUPPORTED_SUBTYPE) 808 { 809 #if DEBUG_PRINT 810 printf("Unsupported APP SubType\n"); 811 #endif 812 inStream.seekFromCurrentPosition((rtcpLength - 2)*4); 813 return UNSUPPORTED_RTCP_PVSS_APP; 814 } 815 816 int32 curpos = inStream.tellg(); 817 inStream >> app_packet.pvss_app_data.common.sendTime; 818 inStream >> app_packet.pvss_app_data.common.recvRate; 819 inStream >> app_packet.pvss_app_data.common.recvRateInterval; 820 inStream >> app_packet.pvss_app_data.common.playbackBufDepth; 821 inStream >> app_packet.pvss_app_data.common.highestCtrlMediaSeqNum; 822 inStream >> app_packet.pvss_app_data.common.cumulativeBytes; 823 if (inStream.fail()) 824 { 825 return FAIL; 826 } 827 828 829 switch (subType) 830 { 831 case 0: // DRC 832 inStream >> app_packet.pvss_app_data.extraDRC.rebufCount; 833 inStream >> app_packet.pvss_app_data.extraDRC.missingPackets; 834 inStream >> app_packet.pvss_app_data.extraDRC.cumulativePacketsReceived; 835 inStream >> app_packet.pvss_app_data.extraDRC.totalProcessedFrames; 836 inStream >> app_packet.pvss_app_data.extraDRC.totalSkippedFrames; 837 inStream >> app_packet.pvss_app_data.extraDRC.cumulativePacketsLost; 838 839 break; 840 case 1: // BufLow 841 inStream >> app_packet.pvss_app_data.extraBufLow.depletionRateInteger; 842 inStream >> app_packet.pvss_app_data.extraBufLow.depletionRateFraction; 843 844 break; 845 case 2: // BufHigh 846 inStream >> app_packet.pvss_app_data.extraBufHigh.fillRateInteger; 847 inStream >> app_packet.pvss_app_data.extraBufHigh.fillRateFraction; 848 849 break; 850 default: 851 break; 852 } 853 854 if (inStream.fail()) 855 { 856 return FAIL; 857 } 858 859 860 int32 diff = inStream.tellg() - curpos; 861 862 diff = (rtcpLength - 2) * 4 - diff; 863 if (diff < 0) 864 { 865 return FAIL; 866 } 867 else if (diff > 0) 868 { 869 inStream.seekFromCurrentPosition(diff); 870 } 871 872 return RTCP_SUCCESS; 873 } 874