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.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 <stdlib.h> 35 //#include <math.h> 36 #include "rtcp.h" 37 38 #ifndef OSCL_DLL_H_INCLUDED 39 #include "oscl_dll.h" 40 #endif 41 42 // Define entry point for this DLL 43 OSCL_DLL_ENTRY_POINT_DEFAULT() 44 45 46 /* 47 ** Constants 48 */ 49 50 51 /* 52 ** Methods 53 */ 54 RTCP_Base::RTCP_Base(const uint8 version) 55 : rtcpVersion(version) 56 {} 57 58 OSCL_EXPORT_REF RTCP_Base::~RTCP_Base() 59 {} 60 61 62 OSCL_EXPORT_REF RTCP_ReportBlock* RTCP_RR::get_report_block(uint index) 63 { 64 65 66 if (index >= max_report_blocks) 67 { 68 return NULL; 69 } 70 71 if (index >= num_report_blocks) 72 { 73 num_report_blocks = index + 1; 74 } 75 76 if (index < NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS) 77 { 78 return preallocated_reports + index; 79 } 80 81 if (!additional_reports) 82 { 83 84 additional_reports = OSCL_ARRAY_NEW(RTCP_ReportBlock, max_report_blocks - NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS); 85 } 86 87 return additional_reports + (index - NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS); 88 89 } 90 91 92 const RTCP_ReportBlock* RTCP_RR::read_report_block(uint index) const 93 { 94 95 96 if (index >= num_report_blocks) 97 { 98 return NULL; 99 } 100 101 if (index < NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS) 102 { 103 return preallocated_reports + index; 104 } 105 106 if (!additional_reports) 107 { 108 return NULL; 109 } 110 111 return additional_reports + (index - NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS); 112 113 } 114 115 116 bool RTCP_RR::set_max_report_blocks(uint new_max_report_blocks) 117 { 118 119 if (additional_reports) 120 { 121 // reports array already exists 122 if (new_max_report_blocks > max_report_blocks) 123 { 124 // only update max if greater than old max 125 max_report_blocks = new_max_report_blocks; 126 if (new_max_report_blocks > NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS) 127 { 128 // free current additional reports and allocate new array 129 delete[] additional_reports; 130 additional_reports = OSCL_ARRAY_NEW(RTCP_ReportBlock, new_max_report_blocks - NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS); 131 } 132 } 133 } 134 else if (new_max_report_blocks > NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS) 135 { 136 // allocate additional_reports array 137 additional_reports = OSCL_ARRAY_NEW(RTCP_ReportBlock, new_max_report_blocks - NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS); 138 max_report_blocks = new_max_report_blocks; 139 } 140 141 return true; 142 143 } 144 145 146 bool RTCP_RR::set_report_block(uint index, const RTCP_ReportBlock& report_block) 147 { 148 if (index >= max_report_blocks) 149 { 150 return false; 151 } 152 153 if (index < NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS) 154 { 155 156 preallocated_reports[index] = report_block; 157 158 } 159 else if (!additional_reports) 160 { 161 // allocate the additional reports array 162 additional_reports = OSCL_ARRAY_NEW(RTCP_ReportBlock, max_report_blocks - NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS); 163 additional_reports[index - NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS] = 164 report_block; 165 } 166 else 167 { 168 169 additional_reports[index - NUM_PREALLOCATED_RTCP_RR_REPORT_BLOCKS] = 170 report_block; 171 172 } 173 174 num_report_blocks = index + 1; 175 return true; 176 } 177 178 179 RTCP_ReportBlock* RTCP_SR::get_report_block(uint index) 180 { 181 182 183 if (index >= max_report_blocks) 184 { 185 return NULL; 186 } 187 188 if (index >= num_report_blocks) 189 { 190 num_report_blocks = index + 1; 191 } 192 193 if (index < NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS) 194 { 195 return preallocated_reports + index; 196 } 197 198 if (!additional_reports) 199 { 200 additional_reports = OSCL_ARRAY_NEW(RTCP_ReportBlock, max_report_blocks - NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS); 201 202 } 203 204 return additional_reports + (index - NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS); 205 206 } 207 208 209 const RTCP_ReportBlock* RTCP_SR::read_report_block(uint index) const 210 { 211 212 if (index >= num_report_blocks) 213 { 214 return NULL; 215 } 216 217 if (index < NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS) 218 { 219 return preallocated_reports + index; 220 } 221 222 if (!additional_reports) 223 { 224 return NULL; 225 } 226 227 return additional_reports + (index - NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS); 228 229 } 230 231 232 bool RTCP_SR::set_max_report_blocks(uint new_max_report_blocks) 233 { 234 235 if (additional_reports) 236 { 237 // reports array already exists 238 if (new_max_report_blocks > max_report_blocks) 239 { 240 // only update max if greater than old max 241 max_report_blocks = new_max_report_blocks; 242 if (new_max_report_blocks > NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS) 243 { 244 // free current additional reports and allocate new array 245 delete[] additional_reports; 246 additional_reports = OSCL_ARRAY_NEW(RTCP_ReportBlock, new_max_report_blocks - NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS); 247 } 248 } 249 } 250 else if (new_max_report_blocks > NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS) 251 { 252 // allocate additional_reports array 253 additional_reports = OSCL_ARRAY_NEW(RTCP_ReportBlock, new_max_report_blocks - NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS); 254 max_report_blocks = new_max_report_blocks; 255 } 256 257 return true; 258 259 } 260 261 262 bool RTCP_SR::set_report_block(uint index, const RTCP_ReportBlock& report_block) 263 { 264 if (index >= max_report_blocks) 265 { 266 return false; 267 } 268 269 if (index < NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS) 270 { 271 272 preallocated_reports[index] = report_block; 273 274 } 275 else if (!additional_reports) 276 { 277 // allocate the additional reports array 278 additional_reports = OSCL_ARRAY_NEW(RTCP_ReportBlock, max_report_blocks - NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS); 279 additional_reports[index - NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS] = 280 report_block; 281 } 282 else 283 { 284 285 additional_reports[index - NUM_PREALLOCATED_RTCP_SR_REPORT_BLOCKS] = 286 report_block; 287 288 } 289 290 num_report_blocks = index + 1; 291 return true; 292 } 293 294 295 void SDES_chunk::set_max_items(uint new_max_items) 296 { 297 298 if (new_max_items > max_sdes_items) 299 { 300 // update sdes items 301 max_sdes_items = new_max_items; 302 303 if (new_max_items > NUM_PREALLOCATED_RTCP_CHUNK_ITEMS) 304 { 305 int32 extra_items = new_max_items - NUM_PREALLOCATED_RTCP_CHUNK_ITEMS; 306 307 // now allocate the extra array 308 SDES_item* new_additional = OSCL_ARRAY_NEW(SDES_item, extra_items); 309 310 if (additional_items) 311 { 312 if (num_sdes_items > NUM_PREALLOCATED_RTCP_CHUNK_ITEMS) 313 { 314 // copy old additional to the new array 315 for (uint ii = 0; ii < num_sdes_items - 316 NUM_PREALLOCATED_RTCP_CHUNK_ITEMS; ++ii) 317 { 318 new_additional[ii] = additional_items[ii]; 319 } 320 } 321 delete[] additional_items; 322 } 323 324 additional_items = new_additional; 325 326 } 327 328 } 329 330 } 331 332 333 SDES_item* SDES_chunk::get_item(uint item_index) 334 { 335 if (item_index >= max_sdes_items) 336 { 337 return NULL; 338 } 339 340 if (item_index >= num_sdes_items) 341 { 342 num_sdes_items = item_index + 1; 343 } 344 345 if (item_index >= NUM_PREALLOCATED_RTCP_CHUNK_ITEMS) 346 { 347 if (!additional_items) 348 { 349 additional_items = OSCL_ARRAY_NEW(SDES_item, max_sdes_items - NUM_PREALLOCATED_RTCP_CHUNK_ITEMS); 350 } 351 352 return additional_items + (item_index - NUM_PREALLOCATED_RTCP_CHUNK_ITEMS); 353 } 354 355 return chunk_items + item_index; 356 } 357 358 359 const SDES_item* SDES_chunk::read_item(uint item_index) const 360 { 361 if (item_index >= num_sdes_items) 362 { 363 return NULL; 364 } 365 366 if (item_index >= NUM_PREALLOCATED_RTCP_CHUNK_ITEMS) 367 { 368 if (!additional_items) 369 { 370 return NULL; 371 } 372 373 return additional_items + (item_index - NUM_PREALLOCATED_RTCP_CHUNK_ITEMS); 374 } 375 376 return chunk_items + item_index; 377 } 378 379 380 bool SDES_chunk::add_item(const SDES_item& item) 381 { 382 383 const uint SDES_ARRAY_INCREMENT = 10; 384 385 if (num_sdes_items > max_sdes_items) 386 { 387 // allocate more 388 set_max_items(max_sdes_items + SDES_ARRAY_INCREMENT); 389 } 390 391 if (num_sdes_items >= NUM_PREALLOCATED_RTCP_CHUNK_ITEMS) 392 { 393 if (!additional_items) 394 { 395 additional_items = OSCL_ARRAY_NEW(SDES_item, max_sdes_items - NUM_PREALLOCATED_RTCP_CHUNK_ITEMS); 396 } 397 additional_items[num_sdes_items - NUM_PREALLOCATED_RTCP_CHUNK_ITEMS] = item; 398 chunk_size += item.content.len + 2; 399 } 400 else 401 { 402 403 chunk_items[num_sdes_items] = item; 404 chunk_size += item.content.len + 2; 405 } 406 407 ++num_sdes_items; 408 return true; 409 410 } 411 412 413 414 void RTCP_SDES::set_max_chunks(uint new_max_chunks) 415 { 416 417 if (new_max_chunks > max_chunks) 418 { 419 // update sdes items 420 max_chunks = new_max_chunks; 421 422 if (new_max_chunks > NUM_PREALLOCATED_RTCP_CHUNKS) 423 { 424 int32 extra_chunks = new_max_chunks - NUM_PREALLOCATED_RTCP_CHUNKS; 425 426 // now allocate the extra array 427 SDES_chunk* new_additional = OSCL_ARRAY_NEW(SDES_chunk, extra_chunks); 428 429 if (additional_chunks) 430 { 431 if (chunk_count > NUM_PREALLOCATED_RTCP_CHUNKS) 432 { 433 // copy old additional to the new array 434 for (uint ii = 0; ii < chunk_count - 435 NUM_PREALLOCATED_RTCP_CHUNKS; ++ii) 436 { 437 new_additional[ii] = additional_chunks[ii]; 438 } 439 } 440 delete[] additional_chunks; 441 } 442 443 additional_chunks = new_additional; 444 445 } 446 447 } 448 449 } 450 451 452 SDES_chunk* RTCP_SDES::get_chunk(uint chunk_index) 453 { 454 if (chunk_index >= max_chunks) 455 { 456 return NULL; 457 } 458 459 if (chunk_index >= chunk_count) 460 { 461 chunk_count = chunk_index + 1; 462 } 463 464 if (chunk_index >= NUM_PREALLOCATED_RTCP_CHUNKS) 465 { 466 if (!additional_chunks) 467 { 468 additional_chunks = OSCL_ARRAY_NEW(SDES_chunk, max_chunks - NUM_PREALLOCATED_RTCP_CHUNKS); 469 } 470 471 return additional_chunks + (chunk_index - NUM_PREALLOCATED_RTCP_CHUNKS); 472 } 473 474 return chunk_array + chunk_index; 475 } 476 477 const SDES_chunk* RTCP_SDES::read_chunk(uint chunk_index) const 478 { 479 if (chunk_index >= chunk_count) 480 { 481 return NULL; 482 } 483 484 if (chunk_index >= NUM_PREALLOCATED_RTCP_CHUNKS) 485 { 486 if (!additional_chunks) 487 { 488 return NULL; 489 } 490 491 return additional_chunks + (chunk_index - NUM_PREALLOCATED_RTCP_CHUNKS); 492 } 493 494 return chunk_array + chunk_index; 495 } 496 497 498 bool RTCP_SDES::add_chunk(const SDES_chunk& chunk) 499 { 500 501 const uint SDES_ARRAY_INCREMENT = 10; 502 503 if (chunk_count > max_chunks) 504 { 505 // allocate more 506 set_max_chunks(max_chunks + SDES_ARRAY_INCREMENT); 507 } 508 509 if (chunk_count >= NUM_PREALLOCATED_RTCP_CHUNKS) 510 { 511 if (!additional_chunks) 512 { 513 additional_chunks = OSCL_ARRAY_NEW(SDES_chunk, max_chunks - NUM_PREALLOCATED_RTCP_CHUNKS); 514 } 515 additional_chunks[chunk_count - NUM_PREALLOCATED_RTCP_CHUNKS] = chunk; 516 } 517 else 518 { 519 chunk_array[chunk_count] = chunk; 520 } 521 522 ++chunk_count; 523 return true; 524 525 } 526 527 528 529 530