Changeset 874
- Timestamp:
- Dec 30, 2006 2:46:57 AM (18 years ago)
- Location:
- pjproject/trunk/pjmedia
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjmedia/include/pjmedia/codec.h
r867 r874 254 254 unsigned channel_cnt; /**< Channel count. */ 255 255 pj_uint32_t avg_bps; /**< Average bandwidth in bits/sec */ 256 pj_uint16_t frm_ptime; /**< Base frame ptime in msec. */ 256 pj_uint16_t frm_ptime; /**< Decoder frame ptime in msec. */ 257 pj_uint16_t enc_ptime; /**< Encoder ptime, or zero if it's 258 equal to decoder ptime. */ 257 259 pj_uint8_t pcm_bits_per_sample; /**< Bits/sample in the PCM side */ 258 260 pj_uint8_t pt; /**< Payload type. */ … … 307 309 308 310 /** 309 * Open the codec and initialize with the specified parameter.. 311 * Open the codec and initialize with the specified parameter. 312 * Upon successful initialization, the codec may modify the parameter 313 * and fills in the unspecified values (such as enc_ptime, when 314 * encoder ptime is different than decoder ptime). 310 315 * 311 316 * @param codec The codec instance. … … 315 320 */ 316 321 pj_status_t (*open)(pjmedia_codec *codec, 317 constpjmedia_codec_param *param );322 pjmedia_codec_param *param ); 318 323 319 324 /** -
pjproject/trunk/pjmedia/src/pjmedia-codec/gsm.c
r867 r874 55 55 pj_pool_t *pool ); 56 56 static pj_status_t gsm_codec_open( pjmedia_codec *codec, 57 constpjmedia_codec_param *attr );57 pjmedia_codec_param *attr ); 58 58 static pj_status_t gsm_codec_close( pjmedia_codec *codec ); 59 59 static pj_status_t gsm_codec_modify(pjmedia_codec *codec, … … 389 389 */ 390 390 static pj_status_t gsm_codec_open( pjmedia_codec *codec, 391 constpjmedia_codec_param *attr )391 pjmedia_codec_param *attr ) 392 392 { 393 393 struct gsm_data *gsm_data = codec->codec_data; … … 441 441 442 442 pj_assert(gsm_data != NULL); 443 pj_assert(gsm_data->encoder == NULL && gsm_data->decoder == NULL);443 pj_assert(gsm_data->encoder != NULL && gsm_data->decoder != NULL); 444 444 445 445 gsm_data->vad_enabled = (attr->setting.vad != 0); -
pjproject/trunk/pjmedia/src/pjmedia-codec/ilbc.c
r867 r874 64 64 pj_pool_t *pool ); 65 65 static pj_status_t ilbc_codec_open(pjmedia_codec *codec, 66 constpjmedia_codec_param *attr );66 pjmedia_codec_param *attr ); 67 67 static pj_status_t ilbc_codec_close(pjmedia_codec *codec ); 68 68 static pj_status_t ilbc_codec_modify(pjmedia_codec *codec, … … 365 365 */ 366 366 static pj_status_t ilbc_codec_open(pjmedia_codec *codec, 367 const pjmedia_codec_param *param_attr )367 pjmedia_codec_param *attr ) 368 368 { 369 369 struct ilbc_codec *ilbc_codec = (struct ilbc_codec*)codec; 370 pjmedia_codec_param attr_copy, *attr;371 370 pj_status_t status; 372 371 … … 374 373 pj_assert(ilbc_codec->enc_ready == PJ_FALSE && 375 374 ilbc_codec->dec_ready == PJ_FALSE); 376 377 /* Copy param to temporary location since we need to modify fmtp_mode */378 pj_memcpy(&attr_copy, param_attr, sizeof(*param_attr));379 attr = &attr_copy;380 375 381 376 /* Decoder mode must be set */ … … 392 387 PJ_ASSERT_RETURN(attr->setting.enc_fmtp_mode==20 || 393 388 attr->setting.enc_fmtp_mode==30, PJMEDIA_CODEC_EINMODE); 389 390 /* Update enc_ptime in the param */ 391 if (attr->setting.enc_fmtp_mode != attr->setting.dec_fmtp_mode) { 392 attr->info.enc_ptime = attr->setting.enc_fmtp_mode; 393 } else { 394 attr->info.enc_ptime = 0; 395 } 394 396 395 397 /* Create enc */ -
pjproject/trunk/pjmedia/src/pjmedia-codec/l16.c
r867 r874 60 60 pj_pool_t *pool ); 61 61 static pj_status_t l16_open( pjmedia_codec *codec, 62 constpjmedia_codec_param *attr );62 pjmedia_codec_param *attr ); 63 63 static pj_status_t l16_close( pjmedia_codec *codec ); 64 64 static pj_status_t l16_modify(pjmedia_codec *codec, … … 490 490 491 491 static pj_status_t l16_open(pjmedia_codec *codec, 492 constpjmedia_codec_param *attr )492 pjmedia_codec_param *attr ) 493 493 { 494 494 /* Nothing to do.. */ -
pjproject/trunk/pjmedia/src/pjmedia-codec/speex_codec.c
r867 r874 60 60 pj_pool_t *pool ); 61 61 static pj_status_t spx_codec_open( pjmedia_codec *codec, 62 constpjmedia_codec_param *attr );62 pjmedia_codec_param *attr ); 63 63 static pj_status_t spx_codec_close( pjmedia_codec *codec ); 64 64 static pj_status_t spx_codec_modify(pjmedia_codec *codec, … … 548 548 */ 549 549 static pj_status_t spx_codec_open( pjmedia_codec *codec, 550 constpjmedia_codec_param *attr )550 pjmedia_codec_param *attr ) 551 551 { 552 552 struct spx_private *spx; -
pjproject/trunk/pjmedia/src/pjmedia/g711.c
r867 r874 63 63 pj_pool_t *pool ); 64 64 static pj_status_t g711_open( pjmedia_codec *codec, 65 constpjmedia_codec_param *attr );65 pjmedia_codec_param *attr ); 66 66 static pj_status_t g711_close( pjmedia_codec *codec ); 67 67 static pj_status_t g711_modify(pjmedia_codec *codec, … … 398 398 399 399 static pj_status_t g711_open(pjmedia_codec *codec, 400 constpjmedia_codec_param *attr )400 pjmedia_codec_param *attr ) 401 401 { 402 402 struct g711_private *priv = codec->codec_data; -
pjproject/trunk/pjmedia/src/pjmedia/stream.c
r868 r874 89 89 pjmedia_codec *codec; /**< Codec instance being used. */ 90 90 pjmedia_codec_param codec_param; /**< Codec param. */ 91 pj_int16_t *enc_buf; /**< Encoding buffer, when enc's 92 ptime is different than dec. 93 Otherwise it's NULL. */ 94 95 unsigned enc_samples_per_frame; 96 unsigned enc_buf_size; /**< Encoding buffer size, in 97 samples. */ 98 unsigned enc_buf_pos; /**< First position in buf. */ 99 unsigned enc_buf_count; /**< Number of samples in the 100 encoding buffer. */ 101 91 102 unsigned vad_enabled; /**< VAD enabled in param. */ 92 103 unsigned frame_size; /**< Size of encoded base frame.*/ … … 443 454 444 455 /** 456 * Rebuffer the frame when encoder and decoder has different ptime 457 * (such as when different iLBC modes are used by local and remote) 458 */ 459 static void rebuffer(pjmedia_stream *stream, 460 pjmedia_frame *frame) 461 { 462 /* How many samples are needed */ 463 unsigned count; 464 465 /* Normalize frame */ 466 if (frame->type != PJMEDIA_FRAME_TYPE_AUDIO) 467 frame->size = 0; 468 469 /* Remove used frame from the buffer. */ 470 if (stream->enc_buf_pos) { 471 if (stream->enc_buf_count) { 472 pj_memmove(stream->enc_buf, 473 stream->enc_buf + stream->enc_buf_pos, 474 (stream->enc_buf_count << 1)); 475 } 476 stream->enc_buf_pos = 0; 477 } 478 479 /* Make sure we have space to store the new frame */ 480 pj_assert(stream->enc_buf_count + (frame->size >> 1) < 481 stream->enc_buf_size); 482 483 /* Append new frame to the buffer */ 484 if (frame->size) { 485 pj_memcpy(stream->enc_buf + stream->enc_buf_count, 486 frame->buf, frame->size); 487 stream->enc_buf_count += (frame->size >> 1); 488 } 489 490 /* How many samples are needed */ 491 count = stream->codec_param.info.enc_ptime * 492 stream->port.info.clock_rate / 1000; 493 494 /* See if we have enough samples */ 495 if (stream->enc_buf_count >= count) { 496 497 frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 498 frame->buf = stream->enc_buf; 499 frame->size = (count << 1); 500 501 stream->enc_buf_pos = count; 502 stream->enc_buf_count -= count; 503 504 } else { 505 /* We don't have enough samples */ 506 frame->type = PJMEDIA_FRAME_TYPE_NONE; 507 } 508 } 509 510 511 /** 512 * put_frame_imp() 513 */ 514 static pj_status_t put_frame_imp( pjmedia_port *port, 515 const pjmedia_frame *frame ) 516 { 517 pjmedia_stream *stream = port->port_data.pdata; 518 pjmedia_channel *channel = stream->enc; 519 pj_status_t status = 0; 520 pjmedia_frame frame_out; 521 unsigned ts_len, samples_per_frame; 522 void *rtphdr; 523 int rtphdrlen; 524 525 526 /* Don't do anything if stream is paused */ 527 if (channel->paused) { 528 stream->enc_buf_pos = stream->enc_buf_count = 0; 529 return PJ_SUCCESS; 530 } 531 532 /* Number of samples in the frame */ 533 if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) 534 ts_len = (frame->size >> 1); 535 else 536 ts_len = 0; 537 538 /* Increment transmit duration */ 539 stream->tx_duration += ts_len; 540 541 /* Init frame_out buffer. */ 542 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 543 frame_out.size = 0; 544 545 /* Calculate number of samples per frame */ 546 samples_per_frame = stream->enc_samples_per_frame; 547 548 549 /* If we have DTMF digits in the queue, transmit the digits. 550 * Otherwise encode the PCM buffer. 551 */ 552 if (stream->tx_dtmf_count) { 553 554 create_dtmf_payload(stream, &frame_out); 555 556 /* Encapsulate. */ 557 status = pjmedia_rtp_encode_rtp( &channel->rtp, 558 stream->tx_event_pt, 0, 559 frame_out.size, ts_len, 560 (const void**)&rtphdr, 561 &rtphdrlen); 562 563 } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) { 564 unsigned ts; 565 566 /* Repeatedly call encode if there are multiple frames to be 567 * sent. 568 */ 569 570 for (ts=0; ts<ts_len; ts += samples_per_frame) { 571 pjmedia_frame tmp_out_frame, tmp_in_frame; 572 unsigned bytes_per_sample, max_size; 573 574 /* Nb of bytes in PCM sample */ 575 bytes_per_sample = stream->codec_param.info.pcm_bits_per_sample/8; 576 577 /* Split original PCM input frame into base frame size */ 578 tmp_in_frame.buf = ((char*)frame->buf) + ts * bytes_per_sample; 579 tmp_in_frame.size = samples_per_frame * bytes_per_sample; 580 tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 581 582 /* Set output frame position */ 583 tmp_out_frame.buf = ((char*)frame_out.buf) + frame_out.size; 584 585 max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr) - 586 frame_out.size; 587 588 /* Encode! */ 589 status = stream->codec->op->encode( stream->codec, &tmp_in_frame, 590 max_size, &tmp_out_frame); 591 if (status != PJ_SUCCESS) { 592 LOGERR_((stream->port.info.name.ptr, 593 "Codec encode() error", status)); 594 return status; 595 } 596 597 /* tmp_out_frame.size may be zero for silence frame. */ 598 frame_out.size += tmp_out_frame.size; 599 600 /* Stop processing next PCM frame when encode() returns either 601 * CNG frame or NULL frame. 602 */ 603 if (tmp_out_frame.type!=PJMEDIA_FRAME_TYPE_AUDIO || 604 tmp_out_frame.size==0) 605 { 606 break; 607 } 608 609 } 610 611 /* Encapsulate. */ 612 status = pjmedia_rtp_encode_rtp( &channel->rtp, 613 channel->pt, 0, 614 frame_out.size, ts_len, 615 (const void**)&rtphdr, 616 &rtphdrlen); 617 } else { 618 619 /* Just update RTP session's timestamp. */ 620 status = pjmedia_rtp_encode_rtp( &channel->rtp, 621 0, 0, 622 0, ts_len, 623 (const void**)&rtphdr, 624 &rtphdrlen); 625 626 } 627 628 if (status != PJ_SUCCESS) { 629 LOGERR_((stream->port.info.name.ptr, 630 "RTP encode_rtp() error", status)); 631 return status; 632 } 633 634 /* Check if now is the time to transmit RTCP SR/RR report. 635 * We only do this when stream direction is not "decoding only", because 636 * when it is, check_tx_rtcp() will be handled by get_frame(). 637 */ 638 if (stream->dir != PJMEDIA_DIR_DECODING) { 639 check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts)); 640 } 641 642 /* Do nothing if we have nothing to transmit */ 643 if (frame_out.size == 0) { 644 if (stream->is_streaming) { 645 PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence")); 646 stream->is_streaming = PJ_FALSE; 647 } 648 649 return PJ_SUCCESS; 650 } 651 652 653 /* Copy RTP header to the beginning of packet */ 654 pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr)); 655 656 657 /* Set RTP marker bit if currently not streaming */ 658 if (stream->is_streaming == PJ_FALSE) { 659 pjmedia_rtp_hdr *rtp = channel->out_pkt; 660 661 rtp->m = 1; 662 PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut..")); 663 } 664 665 stream->is_streaming = PJ_TRUE; 666 667 /* Send the RTP packet to the transport. */ 668 (*stream->transport->op->send_rtp)(stream->transport, 669 channel->out_pkt, 670 frame_out.size + 671 sizeof(pjmedia_rtp_hdr)); 672 673 674 /* Update stat */ 675 pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size); 676 677 return PJ_SUCCESS; 678 } 679 680 681 /** 445 682 * put_frame() 446 683 * … … 453 690 { 454 691 pjmedia_stream *stream = port->port_data.pdata; 455 pjmedia_channel *channel = stream->enc;456 pj_status_t status = 0;457 struct pjmedia_frame frame_out;458 unsigned ts_len, samples_per_frame;459 692 pjmedia_frame tmp_in_frame; 460 void *rtphdr; 461 int rtphdrlen; 462 463 464 /* Don't do anything if stream is paused */ 465 if (channel->paused) 466 return PJ_SUCCESS; 467 468 469 /* Number of samples in the frame */ 470 //ts_len = frame->size / 2; 471 ts_len = port->info.samples_per_frame; 472 473 /* Increment transmit duration */ 474 stream->tx_duration += ts_len; 475 476 /* Init frame_out buffer. */ 477 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 478 frame_out.size = 0; 479 480 /* Calculate number of samples per frame */ 481 samples_per_frame = stream->codec_param.info.frm_ptime * 482 stream->codec_param.info.clock_rate * 483 stream->codec_param.info.channel_cnt / 484 1000; 693 unsigned samples_per_frame; 694 695 samples_per_frame = stream->enc_samples_per_frame; 485 696 486 697 /* If VAD is temporarily disabled during creation, feed zero PCM frame … … 500 711 } 501 712 502 503 /* If we have DTMF digits in the queue, transmit the digits.504 * Otherwise encode the PCM buffer.505 */506 if (stream->tx_dtmf_count) {507 508 create_dtmf_payload(stream, &frame_out);509 510 /* Encapsulate. */511 status = pjmedia_rtp_encode_rtp( &channel->rtp,512 stream->tx_event_pt, 0,513 frame_out.size, ts_len,514 (const void**)&rtphdr,515 &rtphdrlen);516 517 } else if (frame->type != PJMEDIA_FRAME_TYPE_NONE) {518 unsigned ts;519 520 /* Repeatedly call encode if there are multiple frames to be521 * sent.522 */523 524 for (ts=0; ts<ts_len; ts += samples_per_frame) {525 pjmedia_frame tmp_out_frame, tmp_in_frame;526 unsigned bytes_per_sample, max_size;527 528 /* Nb of bytes in PCM sample */529 bytes_per_sample = stream->codec_param.info.pcm_bits_per_sample/8;530 531 /* Split original PCM input frame into base frame size */532 tmp_in_frame.buf = ((char*)frame->buf) + ts * bytes_per_sample;533 tmp_in_frame.size = samples_per_frame * bytes_per_sample;534 tmp_in_frame.type = PJMEDIA_FRAME_TYPE_AUDIO;535 536 /* Set output frame position */537 tmp_out_frame.buf = ((char*)frame_out.buf) + frame_out.size;538 539 max_size = channel->out_pkt_size - sizeof(pjmedia_rtp_hdr) -540 frame_out.size;541 542 /* Encode! */543 status = stream->codec->op->encode( stream->codec, &tmp_in_frame,544 max_size, &tmp_out_frame);545 if (status != PJ_SUCCESS) {546 LOGERR_((stream->port.info.name.ptr,547 "Codec encode() error", status));548 return status;549 }550 551 /* tmp_out_frame.size may be zero for silence frame. */552 frame_out.size += tmp_out_frame.size;553 554 /* Stop processing next PCM frame when encode() returns either555 * CNG frame or NULL frame.556 */557 if (tmp_out_frame.type!=PJMEDIA_FRAME_TYPE_AUDIO ||558 tmp_out_frame.size==0)559 {560 break;561 }562 563 }564 565 /* Encapsulate. */566 status = pjmedia_rtp_encode_rtp( &channel->rtp,567 channel->pt, 0,568 frame_out.size, ts_len,569 (const void**)&rtphdr,570 &rtphdrlen);571 } else {572 573 /* Just update RTP session's timestamp. */574 status = pjmedia_rtp_encode_rtp( &channel->rtp,575 0, 0,576 0, ts_len,577 (const void**)&rtphdr,578 &rtphdrlen);579 580 }581 582 if (status != PJ_SUCCESS) {583 LOGERR_((stream->port.info.name.ptr,584 "RTP encode_rtp() error", status));585 return status;586 }587 588 /* Check if now is the time to transmit RTCP SR/RR report.589 * We only do this when stream direction is not "decoding only", because590 * when it is, check_tx_rtcp() will be handled by get_frame().591 */592 if (stream->dir != PJMEDIA_DIR_DECODING) {593 check_tx_rtcp(stream, pj_ntohl(channel->rtp.out_hdr.ts));594 }595 596 /* Do nothing if we have nothing to transmit */597 if (frame_out.size == 0) {598 if (stream->is_streaming) {599 PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence"));600 stream->is_streaming = PJ_FALSE;601 }602 603 return PJ_SUCCESS;604 }605 606 607 /* Copy RTP header to the beginning of packet */608 pj_memcpy(channel->out_pkt, rtphdr, sizeof(pjmedia_rtp_hdr));609 610 611 /* Set RTP marker bit if currently not streaming */612 if (stream->is_streaming == PJ_FALSE) {613 pjmedia_rtp_hdr *rtp = channel->out_pkt;614 615 rtp->m = 1;616 PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut.."));617 }618 619 stream->is_streaming = PJ_TRUE;620 621 /* Send the RTP packet to the transport. */622 (*stream->transport->op->send_rtp)(stream->transport,623 channel->out_pkt,624 frame_out.size +625 sizeof(pjmedia_rtp_hdr));626 627 628 /* Update stat */629 pjmedia_rtcp_tx_rtp(&stream->rtcp, frame_out.size);630 631 713 /* If VAD is temporarily disabled during creation, enable it 632 714 * after transmitting for VAD_SUSPEND_SEC seconds. … … 642 724 643 725 644 return PJ_SUCCESS; 645 } 726 /* If encoder has different ptime than decoder, then the frame must 727 * be passed through the encoding buffer via rebuffer() function. 728 */ 729 if (stream->enc_buf != NULL) { 730 pjmedia_frame tmp_rebuffer_frame; 731 pj_status_t status = PJ_SUCCESS; 732 733 /* Copy original frame to temporary frame since we need 734 * to modify it. 735 */ 736 pj_memcpy(&tmp_rebuffer_frame, frame, sizeof(pjmedia_frame)); 737 738 /* Loop while we have full frame in enc_buffer */ 739 for (;;) { 740 pj_status_t st; 741 742 /* Run rebuffer() */ 743 rebuffer(stream, &tmp_rebuffer_frame); 744 745 /* Process this frame */ 746 st = put_frame_imp(port, &tmp_rebuffer_frame); 747 if (st != PJ_SUCCESS) 748 status = st; 749 750 /* If we still have full frame in the buffer, re-run 751 * rebuffer() with NULL frame. 752 */ 753 if (stream->enc_buf_count >= stream->enc_samples_per_frame) { 754 755 tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE; 756 757 } else { 758 759 /* Otherwise break */ 760 break; 761 } 762 } 763 764 return status; 765 766 } else { 767 return put_frame_imp(port, frame); 768 } 769 } 770 646 771 647 772 #if 0 … … 1072 1197 goto err_cleanup; 1073 1198 1199 /* If encoder and decoder's ptime are asymmetric, then we need to 1200 * create buffer on the encoder side. This could happen for example 1201 * with iLBC 1202 */ 1203 if (stream->codec_param.info.enc_ptime!=0 && 1204 stream->codec_param.info.enc_ptime!=stream->codec_param.info.frm_ptime) 1205 { 1206 unsigned ptime; 1207 1208 stream->enc_samples_per_frame = stream->codec_param.info.enc_ptime * 1209 stream->port.info.clock_rate / 1000; 1210 1211 /* Set buffer size as twice the largest ptime value between 1212 * stream's ptime, encoder ptime, or decoder ptime. 1213 */ 1214 1215 ptime = stream->port.info.samples_per_frame * 1000 / 1216 stream->port.info.clock_rate; 1217 1218 if (stream->codec_param.info.enc_ptime > ptime) 1219 ptime = stream->codec_param.info.enc_ptime; 1220 1221 if (stream->codec_param.info.frm_ptime > ptime) 1222 ptime = stream->codec_param.info.frm_ptime; 1223 1224 ptime <<= 1; 1225 1226 /* Allocate buffer */ 1227 stream->enc_buf_size = stream->port.info.clock_rate * ptime / 1000; 1228 stream->enc_buf = pj_pool_alloc(pool, stream->enc_buf_size * 2); 1229 1230 } else { 1231 stream->enc_samples_per_frame = stream->port.info.samples_per_frame; 1232 } 1074 1233 1075 1234 /* Initially disable the VAD in the stream, to help traverse NAT better */ … … 1084 1243 /* Get the frame size: */ 1085 1244 1086 stream->frame_size = ( stream->codec_param.info.avg_bps/ 8) *1245 stream->frame_size = ((stream->codec_param.info.avg_bps + 7) / 8) * 1087 1246 stream->codec_param.info.frm_ptime / 1000; 1247 1088 1248 1089 1249 /* Init RTCP session: */
Note: See TracChangeset
for help on using the changeset viewer.