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