• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
RTCP_Decoder(const uint8 version)58 OSCL_EXPORT_REF  RTCP_Decoder::RTCP_Decoder(const uint8 version)
59         : RTCP_Base(version)
60 {
61 
62 }
63 
~RTCP_Decoder()64 OSCL_EXPORT_REF RTCP_Decoder::~RTCP_Decoder()
65 {
66 }
67 
68 OSCL_EXPORT_REF RTCP_Decoder::Error_t
scan_compound_packet(OsclMemoryFragment & input_packet,int32 max_array_size,int32 & filled_size,RTCPPacketType * array_of_packet_types,OsclMemoryFragment * array_of_packets)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 */
DecodeReportBlock(OsclBinIStreamBigEndian & inStream,RTCP_ReportBlock * report)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
DecodeRR(OsclMemoryFragment & input_packet,RTCP_RR & rr_packet)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 */
DecodeSR(const OsclMemoryFragment & input_packet,RTCP_SR & sr_packet)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
DecodeSDES(const OsclMemoryFragment & input_packet,RTCP_SDES & sdes_packet)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
DecodeSDESChunk(OsclBinIStreamBigEndian & inStream,SDES_chunk * sdes_chunk,OsclMemoryFragment & chunk_data)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
DecodeBYE(const OsclMemoryFragment & input_packet,RTCP_BYE & bye_packet)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 */
DecodeAPP(const OsclMemoryFragment & input_packet,RTCP_APP & app_packet)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