• 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_encoder.cpp
23 **
24 **   Description:
25 **      This module implements the RTCP class. This class is used to encode and
26 **      decode RTCP packets. Please refer to the RTCP design document for
27 **      details.
28 */
29 
30 /*
31 ** Includes
32 */
33 
34 #include "oscl_time.h"
35 #include "oscl_mem.h"
36 #include "rtcp_encoder.h"
37 #include "rtcp_constants.h"
38 
39 
40 /*
41 ** Constants
42 */
43 
44 /*
45 ** Methods
46 */
47 
RTCP_Encoder(const uint8 * cname,const int32 cname_len,uint32 ssrc,const uint8 version)48 OSCL_EXPORT_REF RTCP_Encoder::RTCP_Encoder(const uint8 *cname, const int32 cname_len,
49         uint32 ssrc,
50         const uint8 version)
51         : RTCP_Base(version), SSRC(ssrc)
52 {
53 
54     setCName(cname, cname_len);
55 }
56 
57 
setCName(const uint8 * cname,int32 cname_len)58 void RTCP_Encoder::setCName(const uint8 * cname,
59                             int32 cname_len)
60 {
61     if (cname && cname_len)
62     {
63         cName_length = (cname_len < RTCP_ENCODER_MAX_CNAME_SIZE) ? cname_len :
64                        RTCP_ENCODER_MAX_CNAME_SIZE;
65         oscl_memcpy(cName, cname, cName_length);
66     }
67     else
68     {
69         oscl_memcpy(cName, "PVSS", 4);
70         cName_length = 4;
71     }
72 }
73 
74 RTCP_Encoder::Error_t
EncodeReportBlock(OsclBinOStreamBigEndian & outStream,const RTCP_ReportBlock * report)75 RTCP_Encoder::EncodeReportBlock(OsclBinOStreamBigEndian & outStream,/* Input
76                                                                   * stream
77                                                                   * reference
78                                                                   */
79                                 const RTCP_ReportBlock* report
80                                )
81 {
82     if (! report)
83     {
84         return FAIL;
85     }
86 
87     outStream << report->sourceSSRC;
88     const int32 MAX_CUMULATIVE_LOST = 0x7FFFFF;
89 
90     uint32 tempint32 = report->cumulativeNumberOfPacketsLost;
91 
92     if (report->cumulativeNumberOfPacketsLost > MAX_CUMULATIVE_LOST)
93     {
94         tempint32 = MAX_CUMULATIVE_LOST;
95     }
96 
97     tempint32 &= FRACTION_LOST_MASK;
98 
99     tempint32 |= (report->fractionLost) << FRACTION_LOST_POSITION;
100 
101     outStream << tempint32;
102 
103     outStream << report->highestSequenceNumberReceived;
104     outStream << report->interarrivalJitter;
105 
106     outStream << report->lastSR;
107     outStream << report->delaySinceLastSR;
108 
109     if (outStream.fail())
110     {
111         return FAIL;
112     }
113     else
114     {
115         return RTCP_SUCCESS;
116     }
117 }
118 
119 
120 RTCP_Encoder::Error_t
output_rtcp_header(uint8 packet_type,uint8 count_field,uint16 size,OsclBinOStreamBigEndian & outStream,bool pad_bit)121 RTCP_Encoder::output_rtcp_header(uint8 packet_type,
122                                  uint8 count_field,
123                                  uint16 size,
124                                  OsclBinOStreamBigEndian& outStream,
125                                  bool pad_bit)
126 {
127 
128     uint8 tempChar = rtcpVersion << RTPRTCP_VERSION_BIT_POSITION;
129     if (pad_bit)
130     {
131         tempChar |= RTCP_PAD_BIT_MASK;
132     }
133     // transform size into number of 32 bit words - 1
134     size = (size / 4) - 1;
135 
136     tempChar |= count_field & RECORD_COUNT_MASK;
137     outStream << tempChar;
138     outStream << packet_type;
139     outStream << size;
140     if (outStream.fail())
141     {
142         return FAIL;
143     }
144     return RTCP_SUCCESS;
145 }
146 
GetEncodedSize(const RTCP_RR & rr_packet)147 int32 RTCP_Encoder::GetEncodedSize(const RTCP_RR& rr_packet)
148 {
149     uint num_report_blocks = rr_packet.get_num_report_blocks();
150     int32 size = (num_report_blocks * RTCP_REPORT_BLOCK_SIZE) +
151                  RTCP_HEADER_SIZE + RTCP_RR_SENDER_INFO_SIZE;
152 
153     return size;
154 }
155 
GetEncodedSize(const RTCP_SR & sr_packet)156 int32 RTCP_Encoder::GetEncodedSize(const RTCP_SR& sr_packet)
157 {
158     uint num_report_blocks = sr_packet.get_num_report_blocks();
159     int32 size = (num_report_blocks * RTCP_REPORT_BLOCK_SIZE) +
160                  RTCP_HEADER_SIZE + RTCP_SR_SENDER_INFO_SIZE;
161 
162     return size;
163 }
164 
GetEncodedSize(const RTCP_SDES & sdes_packet)165 int32 RTCP_Encoder::GetEncodedSize(const RTCP_SDES& sdes_packet)
166 {
167     uint num_chunks = sdes_packet.get_num_chunks();
168     // now go through the chunks and get the sizes
169 
170     const SDES_chunk* chunk_ptr;
171     int32 size = 0;
172     for (uint ii = 0; ii < num_chunks; ++ii)
173     {
174         if ((chunk_ptr = sdes_packet.read_chunk(ii)) != NULL)
175         {
176             int32 chunk_size = chunk_ptr->get_chunk_size();
177             // add enough for the SSRC, the NULL item, and any padding
178             chunk_size += 8 - (chunk_size & 0x3);
179             size += chunk_size;
180         }
181 
182     }
183 
184     size += RTCP_HEADER_SIZE;
185 
186     return size;
187 }
188 
GetEncodedSize(const RTCP_APP & app_packet)189 int32 RTCP_Encoder::GetEncodedSize(const RTCP_APP& app_packet)
190 {
191     int32 size;
192 
193     if (oscl_memcmp(app_packet.type, PVSS_APP_RTCP_NAME, 4))
194     {
195         // this is a non PVSS APP packet
196         int32 app_data_size = sizeof(RTCP_PSS0_APP);
197         if (app_data_size % 4)
198         {
199             app_data_size += 4 - (app_data_size & 0x3);
200         }
201         size = RTCP_HEADER_SIZE + RTCP_APP_HEADER_INFO_SIZE +
202                app_data_size;
203     }
204     else
205     {
206         size = RTCP_HEADER_SIZE + RTCP_APP_HEADER_INFO_SIZE +
207                RTCP_PVSS_APP_COMMON_SIZE;
208 
209         switch (app_packet.pvss_app_data.subtype)
210         {
211             case DRC_REPORT:
212             {
213                 size += RTCP_PVSS_APP_DRC_SIZE;
214                 break;
215             }
216 
217             case LOW_BUF_WARNING:
218             {
219                 size += RTCP_PVSS_APP_BUFLOW_SIZE;
220                 break;
221             }
222 
223             case HIGH_BUF_WARNING:
224             {
225                 size += RTCP_PVSS_APP_BUFHIGH_SIZE;
226                 break;
227             }
228         }
229     }
230 
231     return size;
232 }
233 
234 
235 
EncodeRR(const RTCP_RR & rr_packet,OsclMemoryFragment & output_buffer,uint8 pad_length)236 RTCP_Encoder::Error_t RTCP_Encoder::EncodeRR(const RTCP_RR& rr_packet,
237         OsclMemoryFragment& output_buffer,
238         uint8 pad_length)
239 {
240     OsclBinOStreamBigEndian outStream;
241 
242     outStream.Attach(1, &output_buffer);
243 
244     // figure out how many bytes will be needed
245     uint num_report_blocks = rr_packet.get_num_report_blocks();
246     uint size = (num_report_blocks * RTCP_REPORT_BLOCK_SIZE) +
247                 RTCP_HEADER_SIZE + RTCP_RR_SENDER_INFO_SIZE + pad_length;
248 
249     if ((size & 0x3) != 0)
250     {
251         // improper pad length -- the packet length must be multiple of 4
252         return INVALID_PAD_LENGTH;
253     }
254 
255     if (output_buffer.len < size)
256     {
257         output_buffer.ptr = 0;
258         output_buffer.len = size;
259         return OUTPUT_TRUNCATED;
260     }
261 
262     Error_t status;
263     if ((status = output_rtcp_header(RR_PACKET_TYPE,
264                                      num_report_blocks,
265                                      size, outStream,
266                                      (pad_length != 0))) !=
267             RTCP_SUCCESS)
268     {
269         return status;
270     }
271 
272     // output the ssrc
273     outStream << rr_packet.senderSSRC;
274     if (outStream.fail())
275     {
276         return FAIL;
277     }
278 
279     // output the report blocks
280     for (uint ii = 0; ii < num_report_blocks; ++ii)
281     {
282         if ((status = EncodeReportBlock(outStream, rr_packet.read_report_block(ii))) != RTCP_SUCCESS)
283         {
284             return status;
285         }
286 
287     }
288 
289     // output any pad bits
290     if (pad_length)
291     {
292         uint8 pad_value = 0;
293         for (int32 ii = 0; ii < pad_length - 1; ++ii)
294         {
295             outStream << pad_value;
296         }
297         outStream << pad_length;
298         if (outStream.fail())
299         {
300             return FAIL;
301         }
302     }
303 
304     output_buffer.len = outStream.tellg();
305 
306     return RTCP_SUCCESS;
307 }
308 
309 
EncodeSR(const RTCP_SR & sr_packet,OsclMemoryFragment & output_buffer,uint8 pad_length)310 RTCP_Encoder::Error_t RTCP_Encoder::EncodeSR(const RTCP_SR& sr_packet,
311         OsclMemoryFragment& output_buffer,
312         uint8 pad_length)
313 {
314     OsclBinOStreamBigEndian outStream;
315 
316     outStream.Attach(1, &output_buffer);
317 
318     // figure out how many bytes will be needed
319     uint num_report_blocks = sr_packet.get_num_report_blocks();
320     uint size = (num_report_blocks * RTCP_REPORT_BLOCK_SIZE) +
321                 RTCP_HEADER_SIZE + RTCP_SR_SENDER_INFO_SIZE + pad_length;
322 
323     if ((size & 0x3) != 0)
324     {
325         // improper pad length -- the packet length must be multiple of 4
326         return INVALID_PAD_LENGTH;
327     }
328 
329     if (output_buffer.len < size)
330     {
331         output_buffer.ptr = 0;
332         output_buffer.len = size;
333         return OUTPUT_TRUNCATED;
334     }
335 
336     Error_t status;
337     if ((status = output_rtcp_header(SR_PACKET_TYPE, num_report_blocks,
338                                      size, outStream,
339                                      (pad_length != 0))) !=
340             RTCP_SUCCESS)
341     {
342         return status;
343     }
344 
345     // output the sender information
346     outStream << sr_packet.senderSSRC;
347     outStream << sr_packet.NTP_timestamp_high;
348     outStream << sr_packet.NTP_timestamp_low;
349     outStream << sr_packet.RTP_timestamp;
350     outStream << sr_packet.packet_count;
351     outStream << sr_packet.octet_count;
352 
353     if (outStream.fail())
354     {
355         return FAIL;
356     }
357 
358     // output the report blocks
359     for (uint ii = 0; ii < num_report_blocks; ++ii)
360     {
361         if ((status = EncodeReportBlock(outStream, sr_packet.read_report_block(ii))) != RTCP_SUCCESS)
362         {
363             return status;
364         }
365 
366     }
367 
368     // output any pad bits
369     if (pad_length)
370     {
371         uint8 pad_value = 0;
372         for (int32 ii = 0; ii < pad_length - 1; ++ii)
373         {
374             outStream << pad_value;
375         }
376         outStream << pad_length;
377         if (outStream.fail())
378         {
379             return FAIL;
380         }
381     }
382 
383     output_buffer.len = outStream.tellg();
384 
385     return RTCP_SUCCESS;
386 }
387 
388 
389 
EncodeBYE(const RTCP_BYE & bye_packet,OsclMemoryFragment & output_buffer,uint8 pad_length)390 RTCP_Encoder::Error_t RTCP_Encoder::EncodeBYE(const RTCP_BYE& bye_packet,
391         OsclMemoryFragment& output_buffer,
392         uint8 pad_length)
393 {
394     OsclBinOStreamBigEndian outStream;
395 
396     outStream.Attach(1, &output_buffer);
397 
398     // figure out how many bytes will be needed
399     int32 ssrc_count = bye_packet.src_count & RECORD_COUNT_MASK;
400     uint size = (ssrc_count * sizeof(bye_packet.ssrc_array[0])) +
401                 RTCP_HEADER_SIZE + pad_length;
402 
403     uint8 reason_len = (uint8)(bye_packet.reason_string.len & 0xFF);
404     uint8 reason_len_pad = 0;
405     if (bye_packet.reason_string.ptr && reason_len)
406     {
407         // figure out how many bytes in the reason string including any padding
408         reason_len_pad = reason_len + 1;
409         if (reason_len_pad & 0x3)
410         {
411             reason_len_pad += (4 - (reason_len_pad & 0x3));
412             size += reason_len + reason_len_pad;
413         }
414     }
415 
416     if ((size & 0x3) != 0)
417     {
418         // improper pad length -- the packet length must be multiple of 4
419         return INVALID_PAD_LENGTH;
420     }
421 
422     if (output_buffer.len < size)
423     {
424         output_buffer.ptr = 0;
425         output_buffer.len = size;
426         return OUTPUT_TRUNCATED;
427     }
428 
429     Error_t status;
430     if ((status = output_rtcp_header(RR_PACKET_TYPE, ssrc_count,
431                                      size, outStream,
432                                      (pad_length != 0))) !=
433             RTCP_SUCCESS)
434     {
435         return status;
436     }
437 
438     for (int32 ii = 0; ii < ssrc_count; ++ii)
439     {
440         outStream << bye_packet.ssrc_array[ii];
441     }
442 
443     if (outStream.fail())
444     {
445         return FAIL;
446     }
447 
448     // output the reason string if any
449     if (reason_len)
450     {
451         outStream << reason_len;
452         outStream.write((int8*)bye_packet.reason_string.ptr,
453                         reason_len);
454         uint8 tmpchar = 0;
455         for (int32 jj = 0; jj < reason_len_pad; ++jj)
456         {
457             outStream << tmpchar;
458         }
459         if (outStream.fail())
460         {
461             return FAIL;
462         }
463 
464     }
465 
466 
467     // output any pad bits
468     if (pad_length)
469     {
470         uint8 pad_value = 0;
471         for (int32 ii = 0; ii < pad_length - 1; ++ii)
472         {
473             outStream << pad_value;
474         }
475         outStream << pad_length;
476         if (outStream.fail())
477         {
478             return FAIL;
479         }
480     }
481 
482     output_buffer.len = outStream.tellg();
483 
484     return RTCP_SUCCESS;
485 }
486 
487 
488 RTCP_Encoder::Error_t
EncodeSDESItem(OsclBinOStreamBigEndian & outStream,const SDES_item * item_ptr)489 RTCP_Encoder::EncodeSDESItem(OsclBinOStreamBigEndian& outStream,
490                              const SDES_item* item_ptr)
491 {
492     if (! item_ptr)
493     {
494         return FAIL;
495     }
496 
497     outStream << item_ptr->type;
498 
499     uint8 len = (uint8)(item_ptr->content.len & 0xFF);  // limit to 255 characters
500 
501     outStream << len;
502 
503     outStream.write((int8*)item_ptr->content.ptr,
504                     len);
505 
506     if (outStream.fail())
507     {
508         return FAIL;
509     }
510 
511     return RTCP_SUCCESS;
512 
513 }
514 
515 
516 
517 RTCP_Encoder::Error_t
EncodeSDESChunk(OsclBinOStreamBigEndian & outStream,const SDES_chunk * chunk_ptr)518 RTCP_Encoder::EncodeSDESChunk(OsclBinOStreamBigEndian& outStream,
519                               const SDES_chunk* chunk_ptr)
520 
521 {
522     if (! chunk_ptr)
523     {
524         return FAIL;
525     }
526 
527     outStream << chunk_ptr->ssrc;
528     if (outStream.fail())
529     {
530         return FAIL;
531     }
532 
533     // get the number of items
534     uint num_items = chunk_ptr->get_num_items();
535 
536     // record the position
537     uint32 pos = outStream.tellg();
538 
539     Error_t status;
540     for (uint ii = 0; ii < num_items; ++ii)
541     {
542         if ((status = EncodeSDESItem(outStream, chunk_ptr->read_item(ii))) !=
543                 RTCP_SUCCESS)
544         {
545             return status;
546         }
547     }
548 
549     uint32 len = outStream.tellg() - pos;
550     // Add the null item and any padding to make it to the next 32-bit boundary
551     len = 4 - (len & 0x3);
552 
553     uint8 pad[4] = {0, 0, 0, 0};
554     outStream.write((int8*)pad, len);
555 
556     if (outStream.fail())
557     {
558         return FAIL;
559     }
560 
561     return RTCP_SUCCESS;
562 
563 }
564 
565 
566 
EncodeSDES(const RTCP_SDES & sdes_packet,OsclMemoryFragment & output_buffer,uint8 pad_length)567 RTCP_Encoder::Error_t RTCP_Encoder::EncodeSDES(const RTCP_SDES& sdes_packet,
568         OsclMemoryFragment& output_buffer,
569         uint8 pad_length)
570 {
571     OsclBinOStreamBigEndian outStream;
572 
573     outStream.Attach(1, &output_buffer);
574 
575     // figure out how many bytes will be needed
576     uint num_chunks = sdes_packet.get_num_chunks();
577     int32 size = GetEncodedSize(sdes_packet) + pad_length;
578 
579     if ((size & 0x3) != 0)
580     {
581         // improper pad length -- the packet length must be multiple of 4
582         return INVALID_PAD_LENGTH;
583     }
584 
585     Error_t status;
586     if ((status = output_rtcp_header(SDES_PACKET_TYPE, num_chunks,
587                                      size, outStream,
588                                      (pad_length != 0))) !=
589             RTCP_SUCCESS)
590     {
591         return status;
592     }
593 
594 
595     for (uint ii = 0; ii < num_chunks; ++ii)
596     {
597         if ((status = EncodeSDESChunk(outStream, sdes_packet.read_chunk(ii))) !=
598                 RTCP_SUCCESS)
599         {
600             return status;
601         }
602     }
603 
604 
605     // output any pad bits
606     if (pad_length)
607     {
608         uint8 pad_value = 0;
609         for (int32 ii = 0; ii < pad_length - 1; ++ii)
610         {
611             outStream << pad_value;
612         }
613         outStream << pad_length;
614         if (outStream.fail())
615         {
616             return FAIL;
617         }
618     }
619 
620     output_buffer.len = outStream.tellg();
621 
622     return RTCP_SUCCESS;
623 
624 }
625 
626 
627 
628 
EncodeAPP(const RTCP_APP & app_packet,OsclMemoryFragment & output_buffer,uint8 pad_length)629 RTCP_Encoder::Error_t RTCP_Encoder::EncodeAPP(const RTCP_APP& app_packet,
630         OsclMemoryFragment& output_buffer,
631         uint8 pad_length)
632 {
633     OsclBinOStreamBigEndian outStream;
634 
635     outStream.Attach(1, &output_buffer);
636 
637     // figure out how many bytes will be needed
638     uint size = GetEncodedSize(app_packet) + pad_length;
639 
640     if ((size & 0x3) != 0)
641     {
642         // improper pad length -- the packet length must be multiple of 4
643         return INVALID_PAD_LENGTH;
644     }
645 
646     if (output_buffer.len < size)
647     {
648         output_buffer.ptr = 0;
649         output_buffer.len = size;
650         return OUTPUT_TRUNCATED;
651     }
652 
653     Error_t status;
654     if ((status = output_rtcp_header(APP_PACKET_TYPE, app_packet.subtype,
655                                      size, outStream,
656                                      (pad_length != 0))) !=
657             RTCP_SUCCESS)
658     {
659         return status;
660     }
661 
662     // output the ssrc and type
663     outStream << app_packet.ssrc;
664     outStream.write((int8*)app_packet.type, 4);
665 
666 
667     if (oscl_memcmp(app_packet.type, PSS0_APP_RTCP_NAME, 4) == 0)
668     {
669         outStream << app_packet.pss0_app_data.sourcessrc;
670         outStream << app_packet.pss0_app_data.playoutdelayinms;
671         outStream << app_packet.pss0_app_data.nsn;
672         outStream << app_packet.pss0_app_data.nun;
673         outStream << app_packet.pss0_app_data.freebufferspace; //in 64 byte blocks
674     }
675     else if (oscl_memcmp(app_packet.type, PVSS_APP_RTCP_NAME, 4) == 0)
676     {
677         // output the PVSS common data
678         outStream << app_packet.pvss_app_data.common.sendTime;
679         outStream << app_packet.pvss_app_data.common.recvRate;   // bits/sec
680         outStream << app_packet.pvss_app_data.common.recvRateInterval;
681         outStream << app_packet.pvss_app_data.common.playbackBufDepth;
682         outStream << app_packet.pvss_app_data.common.highestCtrlMediaSeqNum;
683         outStream << app_packet.pvss_app_data.common.cumulativeBytes;
684 
685         switch (app_packet.pvss_app_data.subtype)
686         {
687             case DRC_REPORT:
688             {
689                 outStream << app_packet.pvss_app_data.extraDRC.rebufCount;
690                 outStream << app_packet.pvss_app_data.extraDRC.missingPackets;
691                 outStream << app_packet.pvss_app_data.extraDRC.cumulativePacketsReceived;
692                 outStream << app_packet.pvss_app_data.extraDRC.totalProcessedFrames;
693                 outStream << app_packet.pvss_app_data.extraDRC.totalSkippedFrames;
694                 outStream << app_packet.pvss_app_data.extraDRC.cumulativePacketsLost;
695 
696                 break;
697             }
698 
699             case LOW_BUF_WARNING:
700             {
701                 outStream << app_packet.pvss_app_data.extraBufLow.depletionRateInteger;
702                 outStream << app_packet.pvss_app_data.extraBufLow.depletionRateFraction;
703                 break;
704             }
705 
706             case HIGH_BUF_WARNING:
707             {
708                 outStream << app_packet.pvss_app_data.extraBufHigh.fillRateInteger;
709                 outStream << app_packet.pvss_app_data.extraBufHigh.fillRateFraction;
710 
711                 break;
712             }
713 
714         }
715     }
716     else
717     {
718         // this is not a PVSS APP packet or PSS0 APP packet
719         outStream.write((int8*)app_packet.app_data.ptr,
720                         app_packet.app_data.len);
721 
722         if (app_packet.app_data.len & 0x3)
723         {
724             // pad the data to the next 32-bit boundary
725             int8 pad[4] = {0, 0, 0, 0};
726             outStream.write(pad, 4 - (app_packet.app_data.len & 0x3));
727         }
728     }
729 
730     if (outStream.fail())
731     {
732         return FAIL;
733     }
734 
735     // output any pad bits
736     if (pad_length)
737     {
738         uint8 pad_value = 0;
739         for (int32 ii = 0; ii < pad_length - 1; ++ii)
740         {
741             outStream << pad_value;
742         }
743         outStream << pad_length;
744         if (outStream.fail())
745         {
746             return FAIL;
747         }
748     }
749 
750     output_buffer.len = outStream.tellg();
751 
752     return RTCP_SUCCESS;
753 
754 }
755 
756 
757 OSCL_EXPORT_REF RTCP_Encoder::Error_t
EncodeCompoundRR(const RTCP_RR & rr_packet,OsclMemoryFragment & output_buffer,const RTCP_APP * app_packet,uint8 pad_length)758 RTCP_Encoder::EncodeCompoundRR(const RTCP_RR& rr_packet,
759                                OsclMemoryFragment& output_buffer,
760                                const RTCP_APP* app_packet,
761                                uint8 pad_length)
762 {
763     Error_t status;
764     // encode the RR packet
765     OsclMemoryFragment working_buffer = output_buffer;
766     uint remaining_len = working_buffer.len;
767     if ((status = EncodeRR(rr_packet, working_buffer)) != RTCP_SUCCESS)
768     {
769         return status;
770     }
771 
772     working_buffer.ptr = (uint8*) working_buffer.ptr + working_buffer.len;
773     remaining_len -= working_buffer.len;
774     working_buffer.len = remaining_len;
775 
776     // encode the SDES packet
777     SDES_item cname_item;
778     cname_item.type = CNAME_RTCP_SDES;
779     cname_item.content.ptr = cName;
780     cname_item.content.len = cName_length;
781     SDES_chunk chunk(SSRC);
782     chunk.add_item(cname_item);
783     RTCP_SDES sdes_packet;
784     sdes_packet.add_chunk(chunk);
785     uint8 sdes_pad = (app_packet) ? 0 : pad_length;
786     if ((status = EncodeSDES(sdes_packet, working_buffer, sdes_pad)) != RTCP_SUCCESS)
787     {
788         return status;
789     }
790 
791     working_buffer.ptr = (uint8*) working_buffer.ptr + working_buffer.len;
792     remaining_len -= working_buffer.len;
793     working_buffer.len = remaining_len;
794     if (app_packet)
795     {
796         // encode the app
797         if ((status = EncodeAPP(*app_packet, working_buffer, sdes_pad)) != RTCP_SUCCESS)
798         {
799             return status;
800         }
801 
802         remaining_len -= working_buffer.len;
803     }
804 
805 
806 
807     // update the length field
808     output_buffer.len -= remaining_len;
809 
810 
811     return RTCP_SUCCESS;
812 }
813 
814 
815 RTCP_Encoder::Error_t
EncodeCompoundSR(const RTCP_SR & sr_packet,OsclMemoryFragment & output_buffer,uint8 pad_length)816 RTCP_Encoder::EncodeCompoundSR(const RTCP_SR& sr_packet,
817                                OsclMemoryFragment& output_buffer,
818                                uint8 pad_length)
819 {
820     Error_t status;
821     // encode the SR packet
822     OsclMemoryFragment working_buffer = output_buffer;
823     uint remaining_len = working_buffer.len;
824     if ((status = EncodeSR(sr_packet, working_buffer)) != RTCP_SUCCESS)
825     {
826         return status;
827     }
828 
829     working_buffer.ptr = (uint8*) working_buffer.ptr + working_buffer.len;
830     remaining_len -= working_buffer.len;
831     working_buffer.len = remaining_len;
832 
833     // encode the SDES packet
834     SDES_item cname_item;
835     cname_item.type = CNAME_RTCP_SDES;
836     cname_item.content.ptr = cName;
837     cname_item.content.len = cName_length;
838     SDES_chunk chunk(SSRC);
839     chunk.add_item(cname_item);
840     RTCP_SDES sdes_packet;
841     sdes_packet.add_chunk(chunk);
842     if ((status = EncodeSDES(sdes_packet, working_buffer, pad_length)) != RTCP_SUCCESS)
843     {
844         return status;
845     }
846 
847     remaining_len -= working_buffer.len;
848 
849     // update the length field
850     output_buffer.len -= remaining_len;
851 
852     return RTCP_SUCCESS;
853 }
854