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