Home | History | Annotate | Download | only in src
      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