Changeset 1840
- Timestamp:
- Mar 3, 2008 2:20:41 PM (17 years ago)
- Location:
- pjproject/trunk/pjmedia/src/pjmedia
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/src/pjmedia/delaybuf.c
r1834 r1840 242 242 b->buf_cnt -= erase_cnt; 243 243 244 PJ_LOG(5,(b->obj_name," Successfully shrinking %d samples, "244 PJ_LOG(5,(b->obj_name,"Overflow, %d samples reduced, " 245 245 "buf_cnt=%d", erase_cnt, b->buf_cnt)); 246 246 } … … 533 533 pj_lock_release(b->lock); 534 534 535 PJ_LOG(5,(b->obj_name,"Delay buffer resetted"));535 PJ_LOG(5,(b->obj_name,"Delay buffer is reset")); 536 536 537 537 return PJ_SUCCESS; -
pjproject/trunk/pjmedia/src/pjmedia/splitcomb.c
r1715 r1840 18 18 */ 19 19 #include <pjmedia/splitcomb.h> 20 #include <pjmedia/delaybuf.h> 20 21 #include <pjmedia/errno.h> 21 22 #include <pj/assert.h> … … 29 30 #define TMP_SAMP_TYPE pj_int16_t 30 31 31 /* When delay buffer is used, we only need 1 frame buffering */ 32 #if defined(PJMEDIA_SOUND_USE_DELAYBUF) && PJMEDIA_SOUND_USE_DELAYBUF!=0 33 # define MAX_BUF_CNT 1 34 #else 35 # define MAX_BUF_CNT PJMEDIA_SOUND_BUFFER_COUNT 36 #endif 32 /* Maximum number of channels. */ 33 #define MAX_CHANNELS 16 34 35 /* Maximum number of buffers to be accommodated by delaybuf */ 36 #define MAX_BUF_CNT PJMEDIA_SOUND_BUFFER_COUNT 37 38 /* Maximum number of burst before we pause the media flow */ 39 #define MAX_BURST (buf_cnt + 6) 40 41 /* Maximum number of NULL frames received before we pause the 42 * media flow. 43 */ 44 #define MAX_NULL_FRAMES (rport->max_burst) 45 46 47 /* Operations */ 48 #define OP_PUT (1) 49 #define OP_GET (-1) 50 51 /* Media flow directions */ 52 enum sc_dir 53 { 54 /* This is the direction from the splitcomb to the downstream 55 * port(s), or when put_frame() is called to the splitcomb. 56 */ 57 DIR_DOWNSTREAM, 58 59 /* This is the direction from the downstream port to the splitcomb, 60 * or when get_frame() is called to the splitcomb. 61 */ 62 DIR_UPSTREAM 63 }; 64 65 37 66 38 67 #if 0 … … 44 73 #endif 45 74 46 #if 147 # define LOG_UP_(x) PJ_LOG(5,x)48 # define LOG_DN_(x) PJ_LOG(5,x)49 #else50 # define LOG_UP_(x)51 # define LOG_DN_(x)52 #endif53 75 54 76 /* … … 65 87 pjmedia_port *port; 66 88 pj_bool_t reversed; 67 } port_desc[ 64];89 } port_desc[MAX_CHANNELS]; 68 90 69 91 /* Temporary buffers needed to extract mono frame from … … 85 107 unsigned ch_num; 86 108 109 /* Maximum burst before media flow is suspended */ 110 int max_burst; 111 112 /* Maximum NULL frames received before media flow is suspended. */ 113 unsigned max_null_frames; 114 87 115 /* A reverse port need a temporary buffer to store frame 88 116 * (because of the different phase, see splitcomb.h for details). 89 117 * Since we can not expect get_frame() and put_frame() to be 90 * called evenly one after another, we use circular buffers to 91 * accomodate the "jitter". 92 */ 93 unsigned buf_cnt; 94 95 /* Downstream is the direction when get_frame() is called to the 96 * splitter/combiner port. 97 */ 98 unsigned dn_read_pos, dn_write_pos, 99 dn_overflow_pos, dn_underflow_pos; 100 pj_int16_t *dnstream_buf[MAX_BUF_CNT]; 101 102 /* Upstream is the direction when put_frame() is called to the 103 * splitter/combiner port. 104 */ 105 unsigned up_read_pos, up_write_pos, 106 up_overflow_pos, up_underflow_pos; 107 pj_int16_t *upstream_buf[MAX_BUF_CNT]; 118 * called evenly one after another, we use delay buffers to 119 * accomodate the burst. 120 * 121 * We maintain state for each direction, hence the array. The 122 * array is indexed by direction (sc_dir). 123 */ 124 struct { 125 126 /* The delay buffer where frames will be stored */ 127 pjmedia_delay_buf *dbuf; 128 129 /* Flag to indicate that audio flow on this direction 130 * is currently being suspended (perhaps because nothing 131 * is processing the frame on the other end). 132 */ 133 pj_bool_t paused; 134 135 /* Operation level. When the level exceeds a maximum value, 136 * the media flow on this direction will be paused. 137 */ 138 int level; 139 140 /* Timestamp. */ 141 pj_timestamp ts; 142 143 /* Number of NULL frames transmitted to this port so far. 144 * NULL frame indicate that nothing is transmitted, and 145 * once we get too many of this, we should pause the media 146 * flow to reduce processing. 147 */ 148 unsigned null_cnt; 149 150 } buf[2]; 151 152 /* Must have temporary put buffer for the delay buf, 153 * unfortunately. 154 */ 155 pj_int16_t *tmp_up_buf; 108 156 }; 109 157 … … 229 277 pjmedia_port **p_chport) 230 278 { 231 const pj_str_t name = pj_str("s plitcomb-ch");279 const pj_str_t name = pj_str("scomb-rev"); 232 280 struct splitcomb *sc = (struct splitcomb*) splitcomb; 233 281 struct reverse_port *rport; 234 unsigned i;282 unsigned buf_cnt; 235 283 pjmedia_port *port; 284 pj_status_t status; 236 285 237 286 /* Sanity check */ … … 266 315 267 316 268 rport->buf_cnt = options & 0xFF; 269 if (rport->buf_cnt == 0) 270 rport->buf_cnt = MAX_BUF_CNT; 271 272 /* Create put buffers */ 273 for (i=0; i<rport->buf_cnt; ++i) { 274 rport->dnstream_buf[i]=(pj_int16_t*) 275 pj_pool_zalloc(pool, port->info.bytes_per_frame); 276 PJ_ASSERT_RETURN(rport->dnstream_buf[i], PJ_ENOMEM); 277 } 278 rport->dn_write_pos = rport->buf_cnt/2; 279 280 /* Create get buffers */ 281 for (i=0; i<rport->buf_cnt; ++i) { 282 rport->upstream_buf[i] = (pj_int16_t*) 283 pj_pool_zalloc(pool, 284 port->info.bytes_per_frame); 285 PJ_ASSERT_RETURN(rport->upstream_buf[i], PJ_ENOMEM); 286 } 287 rport->up_write_pos = rport->buf_cnt/2; 288 317 buf_cnt = options & 0xFF; 318 if (buf_cnt == 0) 319 buf_cnt = MAX_BUF_CNT; 320 321 rport->max_burst = MAX_BURST; 322 rport->max_null_frames = MAX_NULL_FRAMES; 323 324 /* Create downstream/put buffers */ 325 status = pjmedia_delay_buf_create(pool, "scomb-down", 326 port->info.clock_rate, 327 port->info.samples_per_frame, 328 buf_cnt, -1, 0, 329 &rport->buf[DIR_DOWNSTREAM].dbuf); 330 if (status != PJ_SUCCESS) { 331 return status; 332 } 333 334 /* Create upstream/get buffers */ 335 status = pjmedia_delay_buf_create(pool, "scomb-up", 336 port->info.clock_rate, 337 port->info.samples_per_frame, 338 buf_cnt, -1, 0, 339 &rport->buf[DIR_UPSTREAM].dbuf); 340 if (status != PJ_SUCCESS) { 341 pjmedia_delay_buf_destroy(rport->buf[DIR_DOWNSTREAM].dbuf); 342 return status; 343 } 344 345 /* And temporary upstream/get buffer */ 346 rport->tmp_up_buf = (pj_int16_t*) 347 pj_pool_alloc(pool, port->info.bytes_per_frame); 289 348 290 349 /* Save port in the splitcomb */ … … 295 354 /* Done */ 296 355 *p_chport = port; 297 return PJ_SUCCESS;356 return status; 298 357 } 299 358 … … 336 395 } 337 396 397 /* Update operation on the specified direction */ 398 static void op_update(struct reverse_port *rport, int dir, int op) 399 { 400 char *dir_name[2] = {"downstream", "upstream"}; 401 402 rport->buf[dir].level += op; 403 404 if (op == OP_PUT) { 405 rport->buf[dir].ts.u64 += rport->base.info.samples_per_frame; 406 } 407 408 if (rport->buf[dir].paused) { 409 if (rport->buf[dir].level < -rport->max_burst) { 410 /* Prevent the level from overflowing and resets back to zero */ 411 rport->buf[dir].level = -rport->max_burst; 412 } else if (rport->buf[dir].level > rport->max_burst) { 413 /* Prevent the level from overflowing and resets back to zero */ 414 rport->buf[dir].level = rport->max_burst; 415 } else { 416 /* Level has fallen below max level, we can resume 417 * media flow. 418 */ 419 PJ_LOG(5,(rport->base.info.name.ptr, 420 "Resuming media flow on %s direction (level=%d)", 421 dir_name[dir], rport->buf[dir].level)); 422 rport->buf[dir].level = 0; 423 rport->buf[dir].paused = PJ_FALSE; 424 425 //This will cause disruption in audio, and it seems to be 426 //working fine without this anyway, so we disable it for now. 427 //pjmedia_delay_buf_learn(rport->buf[dir].dbuf); 428 429 } 430 } else { 431 if (rport->buf[dir].level >= rport->max_burst || 432 rport->buf[dir].level <= -rport->max_burst) 433 { 434 /* Level has reached maximum level, the other side of 435 * rport is not sending/retrieving frames. Pause the 436 * rport on this direction. 437 */ 438 PJ_LOG(5,(rport->base.info.name.ptr, 439 "Pausing media flow on %s direction (level=%d)", 440 dir_name[dir], rport->buf[dir].level)); 441 rport->buf[dir].paused = PJ_TRUE; 442 } 443 } 444 } 445 338 446 339 447 /* … … 354 462 if (!port) continue; 355 463 356 pjmedia_port_put_frame(port, frame); 464 if (!sc->port_desc[ch].reversed) { 465 pjmedia_port_put_frame(port, frame); 466 } else { 467 struct reverse_port *rport = (struct reverse_port*)port; 468 469 /* Write zero port to delaybuf so that it doesn't underflow. 470 * If we don't do this, get_frame() on this direction will 471 * cause delaybuf to generate missing frame and the last 472 * frame transmitted to delaybuf will be replayed multiple 473 * times, which doesn't sound good. 474 */ 475 476 /* Update the number of NULL frames received. Once we have too 477 * many of this, we'll stop calling op_update() to let the 478 * media be suspended. 479 */ 480 481 if (++rport->buf[DIR_DOWNSTREAM].null_cnt > 482 rport->max_null_frames) 483 { 484 /* Prevent the counter from overflowing and resetting 485 * back to zero 486 */ 487 rport->buf[DIR_DOWNSTREAM].null_cnt = 488 rport->max_null_frames + 1; 489 continue; 490 } 491 492 /* Update rport state. */ 493 op_update(rport, DIR_DOWNSTREAM, OP_PUT); 494 495 /* Discard frame if rport is paused on this direction */ 496 if (rport->buf[DIR_DOWNSTREAM].paused) 497 continue; 498 499 /* Generate zero frame. */ 500 pjmedia_zero_samples(rport->tmp_up_buf, 501 this_port->info.samples_per_frame); 502 503 /* Put frame to delay buffer */ 504 pjmedia_delay_buf_put(rport->buf[DIR_DOWNSTREAM].dbuf, 505 rport->tmp_up_buf); 506 507 } 357 508 } 358 509 return PJ_SUCCESS; … … 373 524 if (!port) 374 525 continue; 526 527 /* Extract the mono frame to temporary buffer */ 528 extract_mono_frame((const pj_int16_t*)frame->buf, sc->put_buf, ch, 529 this_port->info.channel_count, 530 frame->size * 8 / 531 this_port->info.bits_per_sample / 532 this_port->info.channel_count); 375 533 376 534 if (!sc->port_desc[ch].reversed) { 377 535 /* Write to normal port */ 378 536 pjmedia_frame mono_frame; 379 380 /* Extract the mono frame */381 extract_mono_frame((const pj_int16_t*)frame->buf, sc->put_buf, ch,382 this_port->info.channel_count,383 frame->size * 8 /384 this_port->info.bits_per_sample /385 this_port->info.channel_count);386 537 387 538 mono_frame.buf = sc->put_buf; … … 396 547 /* Write to reversed phase port */ 397 548 struct reverse_port *rport = (struct reverse_port*)port; 398 399 if (rport->dn_write_pos == rport->dn_read_pos) { 400 401 /* Only report overflow if the frame is constantly read 402 * by the 'consumer' of the reverse port. 403 * It is possible that nobody reads the buffer, so causing 404 * overflow to happen rapidly, and writing log message this 405 * way does not seem to be wise. 406 */ 407 if (rport->dn_read_pos != rport->dn_overflow_pos) { 408 rport->dn_overflow_pos = rport->dn_read_pos; 409 LOG_DN_((THIS_FILE, "Overflow in downstream direction")); 410 } 411 412 /* Adjust write position */ 413 rport->dn_write_pos = 414 (rport->dn_write_pos + rport->buf_cnt/2) % 415 rport->buf_cnt; 549 550 /* Reset NULL frame counter */ 551 rport->buf[DIR_DOWNSTREAM].null_cnt = 0; 552 553 /* Update rport state. */ 554 op_update(rport, DIR_DOWNSTREAM, OP_PUT); 555 556 if (!rport->buf[DIR_DOWNSTREAM].paused) { 557 pjmedia_delay_buf_put(rport->buf[DIR_DOWNSTREAM].dbuf, 558 sc->put_buf); 416 559 } 417 418 /* Extract mono-frame and put it in downstream buffer */419 extract_mono_frame((const pj_int16_t*)frame->buf,420 rport->dnstream_buf[rport->dn_write_pos],421 ch, this_port->info.channel_count,422 frame->size * 8 /423 this_port->info.bits_per_sample /424 this_port->info.channel_count);425 426 rport->dn_write_pos = (rport->dn_write_pos + 1) %427 rport->buf_cnt;428 560 } 429 561 } … … 444 576 unsigned ch; 445 577 pj_bool_t has_frame = PJ_FALSE; 446 447 /* Clear output frame */448 pjmedia_zero_samples((pj_int16_t*)frame->buf,449 this_port->info.samples_per_frame);450 578 451 579 /* Read frame from each port */ … … 455 583 pj_status_t status; 456 584 457 if (!port) 458 continue; 459 460 /* Read from the port */ 461 if (sc->port_desc[ch].reversed == PJ_FALSE) { 585 if (!port) { 586 pjmedia_zero_samples(sc->get_buf, 587 this_port->info.samples_per_frame / 588 this_port->info.channel_count); 589 590 } else if (sc->port_desc[ch].reversed == PJ_FALSE) { 462 591 /* Read from normal port */ 463 592 mono_frame.buf = sc->get_buf; … … 469 598 mono_frame.type != PJMEDIA_FRAME_TYPE_AUDIO) 470 599 { 471 continue; 600 pjmedia_zero_samples(sc->get_buf, 601 port->info.samples_per_frame); 472 602 } 473 474 /* Combine the mono frame into multichannel frame */475 store_mono_frame((const pj_int16_t*)mono_frame.buf,476 (pj_int16_t*)frame->buf, ch,477 this_port->info.channel_count,478 mono_frame.size * 8 /479 this_port->info.bits_per_sample);480 603 481 604 frame->timestamp.u64 = mono_frame.timestamp.u64; … … 485 608 struct reverse_port *rport = (struct reverse_port*)port; 486 609 487 /* Check for underflows */ 488 if (rport->up_read_pos == rport->up_write_pos) { 489 490 /* Only report underflow if the buffer is constantly filled 491 * up at the other side. 492 * It is possible that nobody writes the buffer, so causing 493 * underflow to happen rapidly, and writing log message this 494 * way does not seem to be wise. 495 */ 496 if (rport->up_write_pos != rport->up_underflow_pos) { 497 rport->up_underflow_pos = rport->up_write_pos; 498 LOG_UP_((THIS_FILE, "Underflow in upstream direction")); 499 } 500 501 /* Adjust read position */ 502 rport->up_read_pos = 503 (rport->up_write_pos - rport->buf_cnt/2) % 504 rport->buf_cnt; 610 /* Update rport state. */ 611 op_update(rport, DIR_UPSTREAM, OP_GET); 612 613 if (!rport->buf[DIR_UPSTREAM].paused) { 614 pjmedia_delay_buf_get(rport->buf[DIR_UPSTREAM].dbuf, 615 sc->get_buf); 616 617 } else { 618 pjmedia_zero_samples(sc->get_buf, 619 rport->base.info.samples_per_frame); 505 620 } 506 621 507 TRACE_UP_((THIS_FILE, "Upstream read at buffer pos %d", 508 rport->up_read_pos)); 509 510 /* Combine the mono frame into multichannel frame */ 511 store_mono_frame((const pj_int16_t*)rport->upstream_buf[rport->up_read_pos], 512 (pj_int16_t*)frame->buf, ch, 513 this_port->info.channel_count, 514 port->info.samples_per_frame); 515 516 rport->up_read_pos = (rport->up_read_pos + 1) % 517 rport->buf_cnt; 622 frame->timestamp.u64 = rport->buf[DIR_UPSTREAM].ts.u64; 518 623 } 624 625 /* Combine the mono frame into multichannel frame */ 626 store_mono_frame(sc->get_buf, 627 (pj_int16_t*)frame->buf, ch, 628 this_port->info.channel_count, 629 this_port->info.samples_per_frame); 630 519 631 520 632 … … 549 661 { 550 662 struct reverse_port *rport = (struct reverse_port*) this_port; 551 unsigned count;552 663 553 664 pj_assert(frame->size <= rport->base.info.bytes_per_frame); 554 555 /* Check for overflows */556 if (rport->up_write_pos == rport->up_read_pos) {557 558 /* Only report overflow if the frame is constantly read559 * at the other end of the buffer (the multichannel side).560 * It is possible that nobody reads the buffer, so causing561 * overflow to happen rapidly, and writing log message this562 * way does not seem to be wise.563 */564 if (rport->up_read_pos != rport->up_overflow_pos) {565 rport->up_overflow_pos = rport->up_read_pos;566 LOG_UP_((THIS_FILE, "Overflow in upstream direction"));567 }568 569 /* Adjust the write position */570 rport->up_write_pos = (rport->up_read_pos + rport->buf_cnt/2) %571 rport->buf_cnt;572 }573 665 574 666 /* Handle NULL frame */ … … 576 668 TRACE_UP_((THIS_FILE, "Upstream write %d null samples at buf pos %d", 577 669 this_port->info.samples_per_frame, rport->up_write_pos)); 578 pjmedia_zero_samples(rport->upstream_buf[rport->up_write_pos], 670 671 /* Write zero port to delaybuf so that it doesn't underflow. 672 * If we don't do this, get_frame() on this direction will 673 * cause delaybuf to generate missing frame and the last 674 * frame transmitted to delaybuf will be replayed multiple 675 * times, which doesn't sound good. 676 */ 677 678 /* Update the number of NULL frames received. Once we have too 679 * many of this, we'll stop calling op_update() to let the 680 * media be suspended. 681 */ 682 if (++rport->buf[DIR_UPSTREAM].null_cnt > rport->max_null_frames) { 683 /* Prevent the counter from overflowing and resetting back 684 * to zero 685 */ 686 rport->buf[DIR_UPSTREAM].null_cnt = rport->max_null_frames + 1; 687 return PJ_SUCCESS; 688 } 689 690 /* Update rport state. */ 691 op_update(rport, DIR_UPSTREAM, OP_PUT); 692 693 /* Discard frame if rport is paused on this direction */ 694 if (rport->buf[DIR_UPSTREAM].paused) 695 return PJ_SUCCESS; 696 697 /* Generate zero frame. */ 698 pjmedia_zero_samples(rport->tmp_up_buf, 579 699 this_port->info.samples_per_frame); 580 rport->up_write_pos = (rport->up_write_pos+1) % rport->buf_cnt; 581 return PJ_SUCCESS; 700 701 /* Put frame to delay buffer */ 702 return pjmedia_delay_buf_put(rport->buf[DIR_UPSTREAM].dbuf, 703 rport->tmp_up_buf); 582 704 } 583 705 … … 586 708 PJ_EINVAL); 587 709 588 /* Copy normal frame to curcular buffer */ 589 count = frame->size * 8 / this_port->info.bits_per_sample; 590 591 TRACE_UP_((THIS_FILE, "Upstream write %d samples at buf pos %d", 592 count, rport->up_write_pos)); 593 594 595 pjmedia_copy_samples(rport->upstream_buf[rport->up_write_pos], 596 (const pj_int16_t*) frame->buf, count); 597 rport->up_write_pos = (rport->up_write_pos+1) % rport->buf_cnt; 598 599 return PJ_SUCCESS; 710 /* Reset NULL frame counter */ 711 rport->buf[DIR_UPSTREAM].null_cnt = 0; 712 713 /* Update rport state. */ 714 op_update(rport, DIR_UPSTREAM, OP_PUT); 715 716 /* Discard frame if rport is paused on this direction */ 717 if (rport->buf[DIR_UPSTREAM].paused) 718 return PJ_SUCCESS; 719 720 /* Unfortunately must copy to temporary buffer since delay buf 721 * modifies the frame content. 722 */ 723 pjmedia_copy_samples(rport->tmp_up_buf, (const pj_int16_t*)frame->buf, 724 this_port->info.samples_per_frame); 725 726 /* Put frame to delay buffer */ 727 return pjmedia_delay_buf_put(rport->buf[DIR_UPSTREAM].dbuf, 728 rport->tmp_up_buf); 600 729 } 601 730 … … 608 737 { 609 738 struct reverse_port *rport = (struct reverse_port*) this_port; 610 unsigned count; 611 612 count = rport->base.info.samples_per_frame; 613 739 740 /* Update state */ 741 op_update(rport, DIR_DOWNSTREAM, OP_GET); 742 743 /* Return no frame if media flow on this direction is being 744 * paused. 745 */ 746 if (rport->buf[DIR_DOWNSTREAM].paused) { 747 frame->type = PJMEDIA_FRAME_TYPE_NONE; 748 return PJ_SUCCESS; 749 } 750 751 /* Get frame from delay buffer */ 614 752 frame->size = this_port->info.bytes_per_frame; 615 753 frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 616 617 /* Check for underflows */ 618 if (rport->dn_read_pos == rport->dn_write_pos) { 619 620 /* Only report underflow if the buffer is constantly filled 621 * up at the other side. 622 * It is possible that nobody writes the buffer, so causing 623 * underflow to happen rapidly, and writing log message this 624 * way does not seem to be wise. 625 */ 626 if (rport->dn_write_pos != rport->dn_underflow_pos) { 627 rport->dn_underflow_pos = rport->dn_write_pos; 628 LOG_DN_((THIS_FILE, "Underflow in downstream direction")); 629 } 630 631 /* Adjust read position */ 632 rport->dn_read_pos = 633 (rport->dn_write_pos - rport->buf_cnt/2) % rport->buf_cnt; 634 635 } 636 637 /* Get the samples from the circular buffer */ 638 pjmedia_copy_samples((pj_int16_t*)frame->buf, 639 rport->dnstream_buf[rport->dn_read_pos], 640 count); 641 rport->dn_read_pos = (rport->dn_read_pos+1) % rport->buf_cnt; 754 frame->timestamp.u64 = rport->buf[DIR_DOWNSTREAM].ts.u64; 755 756 return pjmedia_delay_buf_get(rport->buf[DIR_DOWNSTREAM].dbuf, 757 (short*)frame->buf); 758 } 759 760 761 static pj_status_t rport_on_destroy(pjmedia_port *this_port) 762 { 763 struct reverse_port *rport = (struct reverse_port*) this_port; 764 765 pjmedia_delay_buf_destroy(rport->buf[DIR_DOWNSTREAM].dbuf); 766 pjmedia_delay_buf_destroy(rport->buf[DIR_UPSTREAM].dbuf); 642 767 643 768 return PJ_SUCCESS; 644 769 } 645 770 646 647 static pj_status_t rport_on_destroy(pjmedia_port *this_port)648 {649 /* Nothing to do */650 PJ_UNUSED_ARG(this_port);651 652 return PJ_SUCCESS;653 }654
Note: See TracChangeset
for help on using the changeset viewer.