Ticket #1544: encode_and_pack-4.patch
File encode_and_pack-4.patch, 40.1 KB (added by bennylp, 12 years ago) |
---|
-
pjsip-apps/src/samples/streamutil.c
67 67 " --send-recv Set stream direction to bidirectional. \n" 68 68 " --send-only Set stream direction to send only \n" 69 69 " --recv-only Set stream direction to recv only (default) \n" 70 " --ptime=MSEC Set packet payload length to MSEC \n" 70 71 71 72 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 72 73 " --use-srtp[=NAME] Enable SRTP with crypto suite NAME \n" … … 110 111 static pj_status_t create_stream( pj_pool_t *pool, 111 112 pjmedia_endpt *med_endpt, 112 113 const pjmedia_codec_info *codec_info, 114 pjmedia_codec_param *codec_param, 113 115 pjmedia_dir dir, 114 116 pj_uint16_t local_port, 115 117 const pj_sockaddr_in *rem_addr, … … 132 134 /* Reset stream info. */ 133 135 pj_bzero(&info, sizeof(info)); 134 136 135 136 137 /* Initialize stream info formats */ 137 138 info.type = PJMEDIA_TYPE_AUDIO; 138 139 info.dir = dir; 139 140 pj_memcpy(&info.fmt, codec_info, sizeof(pjmedia_codec_info)); 140 info.tx_pt = codec_info->pt; 141 info.param = codec_param; 142 info.tx_pt = info.rx_pt = codec_info->pt; 141 143 info.ssrc = pj_rand(); 142 144 info.tx_event_pt = info.rx_event_pt = PJMEDIA_RTP_PT_TELEPHONE_EVENTS; 145 143 146 #if PJMEDIA_HAS_RTCP_XR && PJMEDIA_STREAM_ENABLE_XR 144 147 /* Set default RTCP XR enabled/disabled */ 145 148 info.rtcp_xr_enabled = PJ_TRUE; … … 229 232 pjmedia_stream *stream = NULL; 230 233 pjmedia_port *stream_port; 231 234 char tmp[10]; 235 unsigned ptime = 0; 232 236 pj_status_t status; 233 237 234 238 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) … … 261 265 OPT_SEND_RECV = 'b', 262 266 OPT_SEND_ONLY = 's', 263 267 OPT_RECV_ONLY = 'i', 268 OPT_PTIME = 't', 264 269 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 265 270 OPT_USE_SRTP = 'S', 266 271 #endif … … 278 283 { "send-recv", 0, 0, OPT_SEND_RECV }, 279 284 { "send-only", 0, 0, OPT_SEND_ONLY }, 280 285 { "recv-only", 0, 0, OPT_RECV_ONLY }, 286 { "ptime", 1, 0, OPT_PTIME }, 281 287 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 282 288 { "use-srtp", 2, 0, OPT_USE_SRTP }, 283 289 { "srtp-tx-key", 1, 0, OPT_SRTP_TX_KEY }, … … 349 355 dir = PJMEDIA_DIR_DECODING; 350 356 break; 351 357 358 case OPT_PTIME: 359 ptime = atoi(pj_optarg); 360 if (ptime < 10 || ptime > 2000) { 361 puts("ptime doesn't seem to be valid."); 362 return 1; 363 } 364 break; 365 352 366 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 353 367 case OPT_USE_SRTP: 354 368 use_srtp = PJ_TRUE; … … 381 395 382 396 } 383 397 384 385 398 /* Verify arguments. */ 386 399 if (dir & PJMEDIA_DIR_ENCODING) { 387 400 if (remote_addr.sin_addr.s_addr == 0) { … … 448 461 0, &codec_info); 449 462 } 450 463 464 /* Get codec default param for info */ 465 status = pjmedia_codec_mgr_get_default_param( 466 pjmedia_endpt_get_codec_mgr(med_endpt), 467 codec_info, 468 &codec_param); 469 /* Should be ok, as create_stream() above succeeded */ 470 pj_assert(status == PJ_SUCCESS); 471 472 /* Set frames per packet */ 473 if (ptime) { 474 codec_param.setting.frm_per_pkt = ptime / codec_param.info.frm_ptime; 475 PJ_LOG(4,(THIS_FILE, "Setting frm_per_pkt to %d", 476 codec_param.setting.frm_per_pkt)); 477 } 478 451 479 /* Create stream based on program arguments */ 452 status = create_stream(pool, med_endpt, codec_info, dir, local_port, 480 status = create_stream(pool, med_endpt, codec_info, &codec_param, 481 dir, local_port, 453 482 &remote_addr, 454 483 #if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0) 455 484 use_srtp, &srtp_crypto_suite, … … 459 488 if (status != PJ_SUCCESS) 460 489 goto on_exit; 461 490 462 /* Get codec default param for info */463 status = pjmedia_codec_mgr_get_default_param(464 pjmedia_endpt_get_codec_mgr(med_endpt),465 codec_info,466 &codec_param);467 /* Should be ok, as create_stream() above succeeded */468 pj_assert(status == PJ_SUCCESS);469 470 491 /* Get the port interface of the stream */ 471 492 status = pjmedia_stream_get_port( stream, &stream_port); 472 493 PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1); … … 589 610 puts(""); 590 611 puts("Commands:"); 591 612 puts(" s Display media statistics"); 613 puts(" 0-9 Send this DTMF digit(s)"); 592 614 puts(" q Quit"); 593 615 puts(""); 594 616 … … 603 625 print_stream_stat(stream, &codec_param); 604 626 else if (tmp[0] == 'q') 605 627 break; 628 else if (pj_isdigit(tmp[0])) { 629 pj_str_t digits; 630 unsigned i; 606 631 632 for (i=0; i<strlen(tmp); ) { 633 if (!pj_isdigit(tmp[i])) { 634 pj_array_erase(tmp, sizeof(tmp[i]), strlen(tmp)+1, i); 635 } else { 636 ++i; 637 } 638 } 639 640 digits = pj_str(tmp); 641 printf("Sending %d digit(s): %.*s\n", (int)digits.slen, 642 (int)digits.slen, digits.ptr); 643 status = pjmedia_stream_dial_dtmf(stream, &digits); 644 if (status != PJ_SUCCESS) 645 PJ_PERROR(3,(THIS_FILE, status, "Error sending DTMF")); 646 } 647 607 648 } 608 649 609 650 -
pjmedia/include/pjmedia/codec.h
301 301 unsigned cng:1; /**< Comfort Noise Generator. */ 302 302 unsigned penh:1; /**< Perceptual Enhancement */ 303 303 unsigned plc:1; /**< Packet loss concealment */ 304 unsigned pack:1; /**< Enable encode_single()&pack() */ 304 305 unsigned reserved:1; /**< Reserved, must be zero. */ 305 306 pjmedia_codec_fmtp enc_fmtp;/**< Encoder's fmtp params. */ 306 307 pjmedia_codec_fmtp dec_fmtp;/**< Decoder's fmtp params. */ … … 308 309 } pjmedia_codec_param; 309 310 310 311 312 /** 313 * Configuration settings for packing encoded audio frames into a packet or 314 * payload. 315 */ 316 typedef struct pjmedia_codec_pack_cfg pjmedia_codec_pack_cfg; 311 317 318 312 319 /* 313 320 * Forward declaration for pjmedia_codec. 314 321 */ … … 472 479 pj_status_t (*recover)(pjmedia_codec *codec, 473 480 unsigned out_size, 474 481 struct pjmedia_frame *output); 482 483 /** 484 * Encode a single audio frame without performing any packing to 485 * the output. Normally the input frame should have exactly the same 486 * ptime as the codec frame time, however when the codec frame ptime 487 * is 10 ms, this may be called with input frame containing 20ms 488 * worth of samples. 489 * 490 * @param codec The codec instance. 491 * @param input Input audio frame. 492 * @param out_size The length of buffer in the output frame. 493 * @param output The output frame. 494 * 495 * @return PJ_SUCCESS on success or the appropriate error code. 496 */ 497 pj_status_t (*encode_single)(pjmedia_codec *codec, 498 const struct pjmedia_frame *input, 499 unsigned out_size, 500 struct pjmedia_frame *output); 501 502 /** 503 * Pack one or more encoded audio frames into packet, suitable to be 504 * placed as payload of a transport such as RTP. 505 * 506 * @param codec The codec instance. 507 * @param pack_cfg Codec packing settings to specify how audio frames 508 * should be arranged in the output buffer. Use NULL 509 * to use codec's default packing setting. 510 * @param frame_cnt Number of input frames. 511 * @param inputs Input frames, which is an array of encoded frames. 512 * @param out_size Size of the output buffer. 513 * @param output Frame buffer to receive the output. 514 * 515 * @return PJ_SUCCESS on success. 516 */ 517 pj_status_t (*pack)(pjmedia_codec *codec, 518 pjmedia_codec_pack_cfg *pack_cfg, 519 unsigned frame_cnt, 520 pjmedia_frame inputs[], 521 unsigned out_size, 522 struct pjmedia_frame *output); 523 475 524 } pjmedia_codec_op; 476 525 477 526 … … 1103 1152 1104 1153 1105 1154 /** 1155 * Encode a single audio frame without performing any packing to 1156 * the output. Normally the input frame should have exactly the same 1157 * ptime as the codec frame time, however when the codec frame ptime 1158 * is 10 ms, this may be called with input frame containing 20ms 1159 * worth of samples. 1160 * 1161 * @param codec The codec instance. 1162 * @param inp Input audio frame. 1163 * @param out_size The length of buffer in the output frame. 1164 * @param out The output frame. 1165 * 1166 * @return PJ_SUCCESS on success or the appropriate error code. 1167 */ 1168 PJ_INLINE(pj_status_t) pjmedia_codec_encode_single(pjmedia_codec *codec, 1169 const pjmedia_frame *inp, 1170 unsigned out_size, 1171 struct pjmedia_frame *out) 1172 { 1173 if (codec->op && codec->op->encode_single) 1174 return (*codec->op->encode_single)(codec, inp, out_size, out); 1175 else 1176 return PJ_ENOTSUP; 1177 1178 } 1179 1180 1181 /** 1182 * Pack one or more encoded audio frames into packet, suitable to be 1183 * placed as payload of a transport such as RTP. 1184 * 1185 * @param codec The codec instance. 1186 * @param pack_cfg Codec packing settings to specify how audio frames 1187 * should be arranged in the output buffer. Use NULL 1188 * to use codec's default packing setting. 1189 * @param frame_cnt Number of input frames. 1190 * @param inputs Input frames, which is an array of encoded frames. 1191 * @param out_size Size of the output buffer. 1192 * @param output Frame buffer to receive the output. 1193 * 1194 * @return PJ_SUCCESS on success. 1195 */ 1196 PJ_INLINE(pj_status_t) pjmedia_codec_pack(pjmedia_codec *codec, 1197 pjmedia_codec_pack_cfg *pack_cfg, 1198 unsigned frame_cnt, 1199 pjmedia_frame inputs[], 1200 unsigned out_size, 1201 struct pjmedia_frame *output) 1202 { 1203 if (codec->op && codec->op->pack) 1204 return (*codec->op->pack)(codec, pack_cfg, frame_cnt, inputs, 1205 out_size, output); 1206 else 1207 return PJ_ENOTSUP; 1208 } 1209 1210 1211 /** 1106 1212 * @} 1107 1213 */ 1108 1214 -
pjmedia/include/pjmedia/rtp.h
83 83 * header in network byte order. 84 84 */ 85 85 #pragma pack(1) 86 struct pjmedia_rtp_hdr86 typedef struct pjmedia_rtp_hdr 87 87 { 88 88 #if defined(PJ_IS_BIG_ENDIAN) && (PJ_IS_BIG_ENDIAN!=0) 89 89 pj_uint16_t v:2; /**< packet type/version */ … … 103 103 pj_uint16_t seq; /**< sequence number */ 104 104 pj_uint32_t ts; /**< timestamp */ 105 105 pj_uint32_t ssrc; /**< synchronization source */ 106 } ;106 } pjmedia_rtp_hdr; 107 107 #pragma pack() 108 108 109 /**110 * @see pjmedia_rtp_hdr111 */112 typedef struct pjmedia_rtp_hdr pjmedia_rtp_hdr;113 109 114 115 110 /** 116 111 * RTP extendsion header. 117 112 */ 118 struct pjmedia_rtp_ext_hdr113 typedef struct pjmedia_rtp_ext_hdr 119 114 { 120 115 pj_uint16_t profile_data; /**< Profile data. */ 121 116 pj_uint16_t length; /**< Length. */ 122 } ;117 } pjmedia_rtp_ext_hdr; 123 118 124 /**125 * @see pjmedia_rtp_ext_hdr126 */127 typedef struct pjmedia_rtp_ext_hdr pjmedia_rtp_ext_hdr;128 129 130 119 #pragma pack(1) 131 120 132 121 /** 133 122 * Declaration for DTMF telephony-events (RFC2833). 134 123 */ 135 struct pjmedia_rtp_dtmf_event124 typedef struct pjmedia_rtp_dtmf_event 136 125 { 137 126 pj_uint8_t event; /**< Event type ID. */ 138 127 pj_uint8_t e_vol; /**< Event volume. */ 139 128 pj_uint16_t duration; /**< Event duration. */ 140 } ;129 } pjmedia_rtp_dtmf_event; 141 130 142 /**143 * @see pjmedia_rtp_dtmf_event144 */145 typedef struct pjmedia_rtp_dtmf_event pjmedia_rtp_dtmf_event;146 131 147 132 #pragma pack() 148 133 … … 150 135 /** 151 136 * A generic sequence number management, used by both RTP and RTCP. 152 137 */ 153 struct pjmedia_rtp_seq_session138 typedef struct pjmedia_rtp_seq_session 154 139 { 155 140 pj_uint16_t max_seq; /**< Highest sequence number heard */ 156 141 pj_uint32_t cycles; /**< Shifted count of seq number cycles */ 157 142 pj_uint32_t base_seq; /**< Base seq number */ 158 143 pj_uint32_t bad_seq; /**< Last 'bad' seq number + 1 */ 159 144 pj_uint32_t probation; /**< Sequ. packets till source is valid */ 160 } ;145 } pjmedia_rtp_seq_session; 161 146 162 /**163 * @see pjmedia_rtp_seq_session164 */165 typedef struct pjmedia_rtp_seq_session pjmedia_rtp_seq_session;166 147 167 168 148 /** 169 149 * RTP session descriptor. 170 150 */ 171 struct pjmedia_rtp_session151 typedef struct pjmedia_rtp_session 172 152 { 173 153 pjmedia_rtp_hdr out_hdr; /**< Saved hdr for outgoing pkts. */ 154 pj_timestamp next_ts; /**< Timestamp of next packet */ 174 155 pjmedia_rtp_seq_session seq_ctrl; /**< Sequence number management. */ 175 156 pj_uint16_t out_pt; /**< Default outgoing payload type. */ 176 157 pj_uint32_t out_extseq; /**< Outgoing extended seq #. */ 177 158 pj_uint32_t peer_ssrc; /**< Peer SSRC. */ 178 159 pj_uint32_t received; /**< Number of received packets. */ 179 } ;160 } pjmedia_rtp_session; 180 161 181 /**182 * @see pjmedia_rtp_session183 */184 typedef struct pjmedia_rtp_session pjmedia_rtp_session;185 162 186 187 163 /** 188 164 * This structure is used to receive additional information about the 189 165 * state of incoming RTP packet. 190 166 */ 191 struct pjmedia_rtp_status167 typedef struct pjmedia_rtp_status 192 168 { 193 169 union { 194 170 struct flag { … … 219 195 received, the value will be set to zero. 220 196 If base sequence has been restarted, the 221 197 value will be one. */ 222 } ;198 } pjmedia_rtp_status; 223 199 224 200 225 201 /** … … 242 218 243 219 244 220 /** 245 * @see pjmedia_rtp_status246 */247 typedef struct pjmedia_rtp_status pjmedia_rtp_status;248 249 250 /**251 221 * This function will initialize the RTP session according to given parameters. 252 222 * 253 223 * @param ses The session. -
pjmedia/src/pjmedia-codec/opencore_amrnb.c
100 100 static pj_status_t amr_codec_recover(pjmedia_codec *codec, 101 101 unsigned output_buf_len, 102 102 struct pjmedia_frame *output); 103 static pj_status_t amr_codec_encode_single(pjmedia_codec *codec, 104 const struct pjmedia_frame *input, 105 unsigned out_size, 106 struct pjmedia_frame *output); 107 static pj_status_t amr_codec_pack(pjmedia_codec *codec, 108 pjmedia_codec_pack_cfg *pack_cfg, 109 unsigned frame_cnt, 110 pjmedia_frame inputs[], 111 unsigned out_size, 112 struct pjmedia_frame *output); 103 113 104 114 105 115 … … 113 123 &amr_codec_parse, 114 124 &amr_codec_encode, 115 125 &amr_codec_decode, 116 &amr_codec_recover 126 &amr_codec_recover, 127 &amr_codec_encode_single, 128 &amr_codec_pack 117 129 }; 118 130 119 131 /* Definition for AMR-NB codec factory operations. */ … … 314 326 attr->setting.frm_per_pkt = 2; 315 327 attr->setting.vad = 1; 316 328 attr->setting.plc = 1; 329 attr->setting.pack = 1; 317 330 318 331 if (def_config.octet_align) { 319 332 attr->setting.dec_fmtp.cnt = 1; … … 623 636 return PJ_SUCCESS; 624 637 } 625 638 639 /* 640 * Encode single frame 641 */ 642 static pj_status_t amr_codec_encode_single(pjmedia_codec *codec, 643 const struct pjmedia_frame *input, 644 unsigned out_size, 645 struct pjmedia_frame *output) 646 { 647 struct amr_data *amr_data = (struct amr_data*) codec->codec_data; 648 pjmedia_codec_amr_bit_info *bit_info; 649 pj_uint8_t *p; 650 int size; 626 651 652 PJ_ASSERT_RETURN(input->size == 160*2, PJMEDIA_CODEC_EPCMFRMINLEN); 653 654 /* Encode */ 655 size = Encoder_Interface_Encode (amr_data->encoder, amr_data->enc_mode, 656 input->buf, output->buf, 0); 657 if (size <= 0) { 658 output->size = 0; 659 output->buf = NULL; 660 output->type = PJMEDIA_FRAME_TYPE_NONE; 661 TRACE_((THIS_FILE, "AMR-NB encode() failed")); 662 return PJMEDIA_CODEC_EFAILED; 663 } 664 665 output->size = size; 666 667 /* Move leading info to bit_info field */ 668 p = (pj_uint8_t*) output->buf; 669 bit_info = (pjmedia_codec_amr_bit_info*) &output->bit_info; 670 bit_info->frame_type = (pj_uint8_t)((*p >> 3) & 0x0F); 671 bit_info->good_quality = (pj_uint8_t)((*p >> 2) & 0x01); 672 bit_info->mode = (pj_int8_t)amr_data->enc_mode; 673 bit_info->start_bit = 0; 674 675 /* Shift buffer due to byte removal */ 676 output->size = (bit_info->frame_type <= 8)? 677 pjmedia_codec_amrnb_framelen[bit_info->frame_type] : 0; 678 pj_memmove(output->buf, (pj_uint8_t*)output->buf + 1, output->size); 679 680 /* It's possible that output->size may be zero now. Not sure if we should 681 * convert the frame to NONE in this case, so just leave this possibility 682 * for now. 683 */ 684 685 return PJ_SUCCESS; 686 } 687 627 688 /* 689 * Pack frames 690 */ 691 static pj_status_t amr_codec_pack(pjmedia_codec *codec, 692 pjmedia_codec_pack_cfg *pack_cfg, 693 unsigned frame_cnt, 694 pjmedia_frame inputs[], 695 unsigned out_size, 696 struct pjmedia_frame *output) 697 { 698 struct amr_data *amr_data = (struct amr_data*) codec->codec_data; 699 unsigned dtx_cnt=0, sid_cnt=0, i; 700 pj_size_t payload_len; 701 pj_status_t status; 702 703 for (i = 0; i < frame_cnt; ++i) { 704 pjmedia_codec_amr_bit_info *info = (pjmedia_codec_amr_bit_info*) 705 &inputs[i].bit_info; 706 707 /* Count the number of SID and DTX frames */ 708 if (info->frame_type == 15) /* DTX*/ 709 ++dtx_cnt; 710 else if (info->frame_type == 8) /* SID */ 711 ++sid_cnt; 712 } 713 714 /* VA generates DTX frames as DTX+SID frames switching quickly and it 715 * seems that the SID frames occur too often (assuming the purpose is 716 * only for keeping NAT alive?). So let's modify the behavior a bit. 717 * Only an SID frame will be sent every PJMEDIA_CODEC_MAX_SILENCE_PERIOD 718 * milliseconds. 719 */ 720 if (sid_cnt + dtx_cnt == frame_cnt) { 721 pj_int32_t dtx_duration; 722 723 dtx_duration = pj_timestamp_diff32(&amr_data->last_tx, 724 &inputs[0].timestamp); 725 if (PJMEDIA_CODEC_MAX_SILENCE_PERIOD == -1 || 726 dtx_duration < PJMEDIA_CODEC_MAX_SILENCE_PERIOD*8000/1000) 727 { 728 output->size = 0; 729 output->type = PJMEDIA_FRAME_TYPE_NONE; 730 output->timestamp = inputs[0].timestamp; 731 return PJ_SUCCESS; 732 } 733 } 734 735 payload_len = out_size; 736 737 status = pjmedia_codec_amr_pack(inputs, frame_cnt, &amr_data->enc_setting, 738 output->buf, &payload_len); 739 if (status != PJ_SUCCESS) { 740 output->size = 0; 741 output->buf = NULL; 742 output->type = PJMEDIA_FRAME_TYPE_NONE; 743 TRACE_((THIS_FILE, "Failed to pack AMR payload, status=%d", status)); 744 return status; 745 } 746 747 output->size = payload_len; 748 output->type = PJMEDIA_FRAME_TYPE_AUDIO; 749 output->timestamp = inputs[0].timestamp; 750 751 amr_data->last_tx = output->timestamp; 752 753 return PJ_SUCCESS; 754 } 755 756 /* 628 757 * Encode frame. 629 758 */ 630 759 static pj_status_t amr_codec_encode( pjmedia_codec *codec, -
pjmedia/src/pjmedia/rtp.c
66 66 /* Initial sequence number SHOULD be random, according to RFC 3550. */ 67 67 /* According to RFC 3711, it should be random within 2^15 bit */ 68 68 ses->out_extseq = pj_rand() & 0x7FFF; 69 ses->peer_ssrc = 0;70 69 71 70 /* Build default header for outgoing RTP packet. */ 72 71 ses->out_hdr.v = RTP_VERSION; 73 ses->out_hdr.p = 0;74 ses->out_hdr.x = 0;75 ses->out_hdr.cc = 0;76 ses->out_hdr.m = 0;77 72 ses->out_hdr.pt = (pj_uint8_t) default_pt; 78 73 ses->out_hdr.seq = (pj_uint16_t) pj_htons( (pj_uint16_t)ses->out_extseq ); 79 ses->out_hdr.ts = 0;80 74 ses->out_hdr.ssrc = sender_ssrc; 81 75 82 76 /* Keep some arguments as session defaults. */ … … 121 115 PJ_UNUSED_ARG(payload_len); 122 116 123 117 /* Update timestamp */ 124 ses->out_hdr.ts = pj_htonl(pj_ntohl(ses->out_hdr.ts)+ts_len); 118 ses->out_hdr.ts = pj_htonl(ses->next_ts.u32.lo); 119 ses->next_ts.u64 += ts_len; 125 120 126 121 /* If payload_len is zero, bail out. 127 122 * This is a clock frame; we're not really transmitting anything. … … 129 124 if (payload_len == 0) 130 125 return PJ_SUCCESS; 131 126 132 /* Update session. */133 ses->out_extseq++;134 135 127 /* Create outgoing header. */ 136 128 ses->out_hdr.pt = (pj_uint8_t) ((pt == -1) ? ses->out_pt : pt); 137 129 ses->out_hdr.m = (pj_uint16_t) m; 138 130 ses->out_hdr.seq = pj_htons( (pj_uint16_t) ses->out_extseq); 139 131 132 /* Update session. */ 133 ses->out_extseq++; 134 140 135 /* Return values */ 141 136 *rtphdr = &ses->out_hdr; 142 137 *hdrlen = sizeof(pjmedia_rtp_hdr); -
pjmedia/src/pjmedia/wav_player.c
591 591 592 592 /* Copy frame from buffer. */ 593 593 frame->type = PJMEDIA_FRAME_TYPE_AUDIO; 594 frame->timestamp.u64 = 0;595 594 596 595 if ((fport->readpos + frame_size) <= (fport->buf + fport->bufsize)) 597 596 { -
pjmedia/src/pjmedia/g711.c
86 86 unsigned output_buf_len, 87 87 struct pjmedia_frame *output); 88 88 #endif 89 static pj_status_t g711_encode_single(pjmedia_codec *codec, 90 const struct pjmedia_frame *input, 91 unsigned out_size, 92 struct pjmedia_frame *output); 93 static pj_status_t g711_pack(pjmedia_codec *codec, 94 pjmedia_codec_pack_cfg *pack_cfg, 95 unsigned frame_cnt, 96 pjmedia_frame inputs[], 97 unsigned out_size, 98 struct pjmedia_frame *output); 89 99 90 100 /* Definition for G711 codec operations. */ 91 101 static pjmedia_codec_op g711_op = … … 98 108 &g711_encode, 99 109 &g711_decode, 100 110 #if !PLC_DISABLED 101 &g711_recover 111 &g711_recover, 102 112 #else 103 NULL 113 NULL, 104 114 #endif 115 g711_encode_single, 116 g711_pack 105 117 }; 106 118 107 119 /* Definition for G711 codec factory operations. */ … … 268 280 /* Enable VAD by default. */ 269 281 attr->setting.vad = 1; 270 282 283 /* encode_single() and pack() may be used */ 284 attr->setting.pack = 1; 285 271 286 /* Default all other flag bits disabled. */ 272 287 273 288 return PJ_SUCCESS; … … 480 495 return PJ_SUCCESS; 481 496 } 482 497 498 static pj_status_t g711_encode_single(pjmedia_codec *codec, 499 const struct pjmedia_frame *input, 500 unsigned output_buf_len, 501 struct pjmedia_frame *output) 502 { 503 return g711_encode(codec, input, output_buf_len, output); 504 } 505 506 static pj_status_t g711_pack(pjmedia_codec *codec, 507 pjmedia_codec_pack_cfg *pack_cfg, 508 unsigned frame_cnt, 509 pjmedia_frame inputs[], 510 unsigned out_size, 511 struct pjmedia_frame *output) 512 { 513 unsigned i; 514 515 output->size = 0; 516 517 for (i=0; i<frame_cnt; ++i) { 518 if (out_size < inputs[i].size) 519 return PJMEDIA_CODEC_EFRMTOOSHORT; 520 pj_memcpy((pj_uint8_t*)output->buf + output->size, 521 inputs[i].buf, inputs[i].size); 522 out_size -= inputs[i].size; 523 output->size += inputs[i].size; 524 } 525 return PJ_SUCCESS; 526 } 527 483 528 static pj_status_t g711_encode(pjmedia_codec *codec, 484 529 const struct pjmedia_frame *input, 485 530 unsigned output_buf_len, -
pjmedia/src/pjmedia/stream.c
51 51 */ 52 52 #define MAX_PLC_MSEC PJMEDIA_MAX_PLC_DURATION_MSEC 53 53 54 /* Maximum size of pack buffer */ 55 #define PACK_BUF_MAX_SIZE PJMEDIA_MAX_MTU 54 56 55 57 /* Tracing jitter buffer operations in a stream session to a CSV file. 56 58 * The trace will contain JB operation timestamp, frame info, RTP info, and … … 73 75 # define PJMEDIA_STREAM_INC 1000 74 76 #endif 75 77 78 #ifndef PJMEDIA_STREAM_MAX_FRAMES_PER_PKT 79 # define PJMEDIA_STREAM_MAX_FRAMES_PER_PKT 32 80 #endif 76 81 82 77 83 /** 78 84 * Media channel. 79 85 */ … … 122 128 123 129 pjmedia_codec *codec; /**< Codec instance being used. */ 124 130 pjmedia_codec_param codec_param; /**< Codec param. */ 131 125 132 pj_int16_t *enc_buf; /**< Encoding buffer, when enc's 126 133 ptime is different than dec. 127 134 Otherwise it's NULL. */ 128 129 135 unsigned enc_samples_per_pkt; 130 136 unsigned enc_buf_size; /**< Encoding buffer size, in 131 137 samples. */ … … 133 139 unsigned enc_buf_count; /**< Number of samples in the 134 140 encoding buffer. */ 135 141 142 pj_uint8_t *pack_buf; /**< Buffer for packing encoded 143 frames, experimental. */ 144 unsigned pack_buf_size; /**< Current size of pack_buf */ 145 unsigned pack_rtp_ts_len;/**< # of samples in pack buf */ 146 unsigned pack_frm_cnt; /**< Number of pack frm. */ 147 pjmedia_frame *pack_frm; /**< Array of yet to be packed 148 frames */ 149 unsigned pack_frm_per_pkt; /**< # of frames per packet. */ 150 136 151 unsigned plc_cnt; /**< # of consecutive PLC frames*/ 137 152 unsigned max_plc_cnt; /**< Max # of PLC frames */ 138 153 139 154 unsigned vad_enabled; /**< VAD enabled in param. */ 140 unsigned frame_size; /**< Size of encoded base frame.*/141 155 pj_bool_t is_streaming; /**< Currently streaming?. This 142 156 is used to put RTP marker 143 157 bit. */ … … 1137 1151 } 1138 1152 } 1139 1153 1154 /* Util */ 1155 static void set_streaming_state(pjmedia_stream *stream, 1156 pj_bool_t is_streaming, 1157 const pj_timestamp *ts) 1158 { 1159 if (is_streaming) { 1160 PJ_LOG(5,(stream->port.info.name.ptr, "Start talksprut")); 1161 } else { 1162 PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence..")); 1163 } 1140 1164 1165 stream->is_streaming = is_streaming; 1166 } 1167 1141 1168 /** 1142 1169 * put_frame_imp() 1143 1170 */ … … 1152 1179 void *rtphdr; 1153 1180 int rtphdrlen; 1154 1181 int inc_timestamp = 0; 1182 pj_bool_t start_talksprut = PJ_FALSE; 1183 enum 1184 { 1185 DO_NOTHING, /* No action (must be bug then!) */ 1186 DO_SEND_DTMF, /* Transmit RFC 2833 DTMF */ 1187 DO_CHECK_SEND_SILENCE, /* Check and TX silence periodically. */ 1188 DO_UPDATE_TS_ONLY, /* Just update RTP timestamp, no TX. */ 1189 DO_WHOLE_ENCODE_AND_SEND,/* Encode audio and send immediately. */ 1190 DO_ENCODE_AND_APPEND, /* New: encode single frame and append 1191 to buffer */ 1192 DO_PACK_AND_SEND, /* New: have enough frames in the buffer, 1193 so pack and send them. */ 1194 } action = DO_NOTHING; 1155 1195 1156 1157 1196 #if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA != 0 1158 1197 /* If the interval since last sending packet is greater than 1159 1198 * PJMEDIA_STREAM_KA_INTERVAL, send keep-alive packet. … … 1192 1231 stream->tx_duration += ts_len; 1193 1232 1194 1233 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG!=0) 1195 /* Handle special case for audio codec with RTP timestamp inconsistenc e1234 /* Handle special case for audio codec with RTP timestamp inconsistency 1196 1235 * e.g: G722, MPEG audio. 1197 1236 */ 1198 1237 if (stream->has_g722_mpeg_bug) … … 1211 1250 samples_per_frame = stream->enc_samples_per_pkt; 1212 1251 1213 1252 1214 /* If we have DTMF digits in the queue, transmit the digits.1215 * Otherwise encode the PCM buffer.1216 */1217 1253 if (stream->tx_dtmf_count) { 1218 int first=0, last=0; 1219 1220 create_dtmf_payload(stream, &frame_out, &first, &last); 1221 1222 /* Encapsulate into RTP packet. Note that: 1223 * - RTP marker should be set on the beginning of a new event 1224 * - RTP timestamp is constant for the same packet. 1225 */ 1226 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1227 stream->tx_event_pt, first, 1228 frame_out.size, 1229 (first ? rtp_ts_len : 0), 1230 (const void**)&rtphdr, 1231 &rtphdrlen); 1232 1233 if (last) { 1234 /* This is the last packet for the event. 1235 * Increment the RTP timestamp of the RTP session, for next 1236 * RTP packets. 1237 */ 1238 inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len; 1254 /* We have DTMF to send. If we currently have frames in the 1255 * pack buffer, flush them so that we can start sending DTMF 1256 * in the next cycle. 1257 */ 1258 if (stream->pack_frm_cnt) { 1259 action = DO_ENCODE_AND_APPEND; 1260 } else { 1261 action = DO_SEND_DTMF; 1239 1262 } 1240 1263 1241 1242 /*1243 * Special treatment for FRAME_TYPE_AUDIO but with frame->buf==NULL.1244 * This happens when stream input is disconnected from the bridge.1245 * In this case we periodically transmit RTP frame to keep NAT binding1246 * open, by giving zero PCM frame to the codec.1247 *1248 * This was originally done in http://trac.pjsip.org/repos/ticket/56,1249 * but then disabled in http://trac.pjsip.org/repos/ticket/439, but1250 * now it's enabled again.1251 */1252 1264 } else if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 1253 1265 frame->buf == NULL && 1254 1266 stream->port.info.fmt.id == PJMEDIA_FORMAT_L16 && … … 1258 1270 stream->codec_param.info.clock_rate/1000 < 1259 1271 PJ_ARRAY_SIZE(zero_frame)) 1260 1272 { 1261 pjmedia_frame silence_frame; 1273 /* 1274 * Special treatment for FRAME_TYPE_AUDIO but with frame->buf==NULL. 1275 * This happens when stream input is disconnected from the bridge. 1276 * In this case we periodically transmit RTP frame to keep NAT binding 1277 * open, by giving zero PCM frame to the codec. 1278 * 1279 * This was originally done in http://trac.pjsip.org/repos/ticket/56, 1280 * but then disabled in http://trac.pjsip.org/repos/ticket/439, but 1281 * now it's enabled again. 1282 */ 1283 if (stream->pack_frm_cnt) { 1284 /* This is the first time we get silence. Check if we already 1285 * have frames in the buffer and flush them. 1286 */ 1287 action = DO_PACK_AND_SEND; 1288 } else { 1289 action = DO_CHECK_SEND_SILENCE; 1290 } 1262 1291 1263 pj_bzero(&silence_frame, sizeof(silence_frame)); 1264 silence_frame.buf = zero_frame; 1265 silence_frame.size = stream->codec_param.info.frm_ptime * 2 * 1266 stream->codec_param.info.channel_cnt * 1267 stream->codec_param.info.clock_rate / 1000; 1268 silence_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 1269 silence_frame.timestamp.u32.lo = pj_ntohl(stream->enc->rtp.out_hdr.ts); 1270 1292 } else if ((frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 1293 frame->buf != NULL) || 1294 (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED)) 1295 { 1296 /* Encode audio frame */ 1297 if (stream->pack_buf) { 1298 action = DO_ENCODE_AND_APPEND; 1299 } else { 1300 action = DO_WHOLE_ENCODE_AND_SEND; 1301 } 1302 } else { 1303 action = DO_UPDATE_TS_ONLY; 1304 } 1305 1306 /* 1307 * Perform action 1308 */ 1309 if (action == DO_WHOLE_ENCODE_AND_SEND) { 1271 1310 /* Encode! */ 1272 status = pjmedia_codec_encode( stream->codec, &silence_frame,1311 status = pjmedia_codec_encode( stream->codec, frame, 1273 1312 channel->out_pkt_size - 1274 1313 sizeof(pjmedia_rtp_hdr), 1275 1314 &frame_out); … … 1277 1316 LOGERR_((stream->port.info.name.ptr, 1278 1317 "Codec encode() error", status)); 1279 1318 return status; 1319 } else if (frame_out.size == 0) { 1320 if (stream->is_streaming) { 1321 set_streaming_state(stream, PJ_FALSE, &frame->timestamp); 1322 } 1323 } else { 1324 if (!stream->is_streaming) { 1325 set_streaming_state(stream, PJ_TRUE, &frame->timestamp); 1326 start_talksprut = PJ_TRUE; 1327 } 1280 1328 } 1281 1329 1282 1330 /* Encapsulate. */ … … 1286 1334 (const void**)&rtphdr, 1287 1335 &rtphdrlen); 1288 1336 1337 } else if (action == DO_ENCODE_AND_APPEND || 1338 action == DO_PACK_AND_SEND) 1339 { 1340 if (action == DO_ENCODE_AND_APPEND) { 1341 /* Encode 1 frame and append to buffer */ 1342 pjmedia_frame *ptr_frm; 1343 unsigned max_size; 1289 1344 1290 /* Encode audio frame */ 1291 } else if ((frame->type == PJMEDIA_FRAME_TYPE_AUDIO && 1292 frame->buf != NULL) || 1293 (frame->type == PJMEDIA_FRAME_TYPE_EXTENDED)) 1294 { 1345 ptr_frm = &stream->pack_frm[stream->pack_frm_cnt]; 1346 ptr_frm->buf = stream->pack_buf + stream->pack_buf_size; 1347 ptr_frm->size = 0; 1348 ptr_frm->timestamp = frame->timestamp; 1349 ptr_frm->bit_info = 0; 1350 max_size = PACK_BUF_MAX_SIZE - stream->pack_buf_size; 1351 1352 /* Encode! */ 1353 status = pjmedia_codec_encode_single(stream->codec, 1354 frame, max_size, 1355 ptr_frm); 1356 if (status != PJ_SUCCESS) { 1357 LOGERR_((stream->port.info.name.ptr, 1358 "Codec encode_single() error", status)); 1359 stream->pack_rtp_ts_len += rtp_ts_len; 1360 action = DO_PACK_AND_SEND; 1361 } else if (ptr_frm->size == 0) { 1362 /* Got silence. Flush frames */ 1363 stream->pack_rtp_ts_len += rtp_ts_len; 1364 action = DO_PACK_AND_SEND; 1365 } else { 1366 unsigned pkt_ptime, target_pkt_ptime; 1367 1368 stream->pack_rtp_ts_len += rtp_ts_len; 1369 ++stream->pack_frm_cnt; 1370 stream->pack_buf_size += ptr_frm->size; 1371 1372 /* Check current buffer's length. It is possible that the 1373 * duration has exceeded the target if put_frame() is called 1374 * with input that contains multiple frames (sample case: 1375 * pcmu and g719 due to it's 10ms frame_ptime) 1376 */ 1377 pkt_ptime = stream->pack_rtp_ts_len * 1000 / 1378 stream->port.info.fmt.det.aud.clock_rate; 1379 target_pkt_ptime = stream->pack_frm_per_pkt * 1380 stream->codec_param.info.frm_ptime; 1381 1382 if (stream->pack_frm_cnt >= stream->pack_frm_per_pkt || 1383 pkt_ptime >= target_pkt_ptime || 1384 stream->tx_dtmf_count) 1385 { 1386 action = DO_PACK_AND_SEND; 1387 } 1388 } 1389 } 1390 1391 if (action == DO_PACK_AND_SEND) { 1392 /* Pack */ 1393 if (stream->pack_frm_cnt) { 1394 status = pjmedia_codec_pack(stream->codec, NULL, 1395 stream->pack_frm_cnt, 1396 stream->pack_frm, 1397 channel->out_pkt_size - 1398 sizeof(pjmedia_rtp_hdr), 1399 &frame_out); 1400 if (status != PJ_SUCCESS) { 1401 LOGERR_((stream->port.info.name.ptr, 1402 "Codec pack() error", status)); 1403 } else { 1404 /* NOTE: frame_out->size may be zero on DTX */ 1405 1406 if (frame_out.size && !stream->is_streaming) { 1407 set_streaming_state(stream, PJ_TRUE, 1408 &frame->timestamp); 1409 start_talksprut = PJ_TRUE; 1410 } 1411 1412 /* Encapsulate. */ 1413 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1414 channel->pt, 0, 1415 frame_out.size, 1416 stream->pack_rtp_ts_len, 1417 (const void**)&rtphdr, 1418 &rtphdrlen); 1419 } 1420 } else { 1421 /* Update RTP session's timestamp. */ 1422 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1423 0, 0, 0, 1424 stream->pack_rtp_ts_len, 1425 (const void**)&rtphdr, 1426 &rtphdrlen); 1427 1428 if (stream->is_streaming) { 1429 set_streaming_state(stream, PJ_FALSE, &frame->timestamp); 1430 } 1431 } 1432 1433 /* Reset no matter what */ 1434 stream->pack_frm_cnt = 0; 1435 stream->pack_buf_size = 0; 1436 stream->pack_rtp_ts_len = 0; 1437 } 1438 1439 } else if (action == DO_SEND_DTMF) { 1440 int first=0, last=0; 1441 1442 create_dtmf_payload(stream, &frame_out, &first, &last); 1443 1444 /* Encapsulate into RTP packet. Note that: 1445 * - RTP marker should be set on the beginning of a new event 1446 * - RTP timestamp is constant for the same packet. 1447 */ 1448 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1449 stream->tx_event_pt, first, 1450 frame_out.size, 1451 0, 1452 (const void**)&rtphdr, 1453 &rtphdrlen); 1454 1455 if (last) { 1456 /* This is the last packet for the event. 1457 * Increment the RTP timestamp of the RTP session, for next 1458 * RTP packets. 1459 */ 1460 inc_timestamp = PJMEDIA_DTMF_DURATION; 1461 } 1462 } else if (action == DO_CHECK_SEND_SILENCE) { 1463 pjmedia_frame silence_frame; 1464 1465 pj_bzero(&silence_frame, sizeof(silence_frame)); 1466 silence_frame.buf = zero_frame; 1467 silence_frame.size = stream->codec_param.info.frm_ptime * 2 * 1468 stream->codec_param.info.channel_cnt * 1469 stream->codec_param.info.clock_rate / 1000; 1470 silence_frame.type = PJMEDIA_FRAME_TYPE_AUDIO; 1471 silence_frame.timestamp.u32.lo = pj_ntohl(stream->enc->rtp.out_hdr.ts); 1472 1295 1473 /* Encode! */ 1296 status = pjmedia_codec_encode( stream->codec, frame,1297 channel->out_pkt_size - 1474 status = pjmedia_codec_encode( stream->codec, &silence_frame, 1475 channel->out_pkt_size - 1298 1476 sizeof(pjmedia_rtp_hdr), 1299 1477 &frame_out); 1300 1478 if (status != PJ_SUCCESS) { 1301 LOGERR_((stream->port.info.name.ptr, 1479 LOGERR_((stream->port.info.name.ptr, 1302 1480 "Codec encode() error", status)); 1303 1481 return status; 1482 } else if (frame_out.size == 0) { 1483 if (stream->is_streaming) { 1484 set_streaming_state(stream, PJ_FALSE, &frame->timestamp); 1485 } 1486 } else { 1487 if (!stream->is_streaming) { 1488 set_streaming_state(stream, PJ_TRUE, &frame->timestamp); 1489 start_talksprut = PJ_TRUE; 1490 } 1304 1491 } 1305 1492 1306 1493 /* Encapsulate. */ 1307 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1308 channel->pt, 0, 1309 frame_out.size, rtp_ts_len, 1310 (const void**)&rtphdr, 1494 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1495 channel->pt, 0, 1496 frame_out.size, rtp_ts_len, 1497 (const void**)&rtphdr, 1311 1498 &rtphdrlen); 1312 1313 } else { 1314 1499 } else if (action == DO_UPDATE_TS_ONLY) { 1315 1500 /* Just update RTP session's timestamp. */ 1316 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1317 0, 0, 1318 0, rtp_ts_len, 1319 (const void**)&rtphdr, 1501 status = pjmedia_rtp_encode_rtp( &channel->rtp, 1502 0, 0, 1503 0, rtp_ts_len, 1504 (const void**)&rtphdr, 1320 1505 &rtphdrlen); 1321 1506 } else { 1507 pj_assert(!"Unknown operation (bug)"); 1322 1508 } 1323 1509 1324 1510 if (status != PJ_SUCCESS) { … … 1337 1523 1338 1524 /* Do nothing if we have nothing to transmit */ 1339 1525 if (frame_out.size == 0) { 1340 if (stream->is_streaming) {1341 PJ_LOG(5,(stream->port.info.name.ptr,"Starting silence"));1342 stream->is_streaming = PJ_FALSE;1343 }1344 1345 1526 return PJ_SUCCESS; 1346 1527 } 1347 1528 … … 1359 1540 } 1360 1541 1361 1542 /* Set RTP marker bit if currently not streaming */ 1362 if (st ream->is_streaming == PJ_FALSE) {1543 if (start_talksprut) { 1363 1544 pjmedia_rtp_hdr *rtp = (pjmedia_rtp_hdr*) channel->out_pkt; 1364 1545 1365 1546 rtp->m = 1; 1366 PJ_LOG(5,(stream->port.info.name.ptr,"Start talksprut.."));1367 1547 } 1368 1548 1369 stream->is_streaming = PJ_TRUE;1370 1371 1549 /* Send the RTP packet to the transport. */ 1372 1550 status = pjmedia_transport_send_rtp(stream->transport, channel->out_pkt, 1373 1551 frame_out.size + … … 1964 2142 pjmedia_stream *stream; 1965 2143 pj_str_t name; 1966 2144 unsigned jb_init, jb_max, jb_min_pre, jb_max_pre; 2145 unsigned jb_frame_size; 1967 2146 pjmedia_audio_format_detail *afd; 1968 2147 pj_pool_t *own_pool = NULL; 1969 2148 char *p; … … 2082 2261 2083 2262 /* Set additional info and callbacks. */ 2084 2263 afd->bits_per_sample = 16; 2085 afd->frame_time_usec = stream->codec_param.info.frm_ptime * 2086 stream->codec_param.setting.frm_per_pkt * 1000; 2264 2265 /* New and experimental: 2266 * Encode and decode frame one by one (only if "pack" is enabled) 2267 */ 2268 if (stream->codec_param.setting.pack && 2269 stream->codec_param.info.frm_ptime * 2270 stream->codec_param.setting.frm_per_pkt >= 40) 2271 { 2272 PJ_ASSERT_RETURN(stream->codec->op->encode_single && 2273 stream->codec->op->pack, PJ_EINVAL); 2274 2275 if (stream->codec_param.setting.frm_per_pkt > 2276 PJMEDIA_STREAM_MAX_FRAMES_PER_PKT) 2277 { 2278 status = PJ_ETOOMANY; 2279 goto err_cleanup; 2280 } 2281 stream->pack_frm = (pjmedia_frame*) 2282 pj_pool_calloc(pool, 2283 PJMEDIA_STREAM_MAX_FRAMES_PER_PKT, 2284 sizeof(pjmedia_frame)); 2285 stream->pack_buf = (pj_uint8_t*) 2286 pj_pool_alloc(pool, PACK_BUF_MAX_SIZE); 2287 2288 stream->pack_frm_per_pkt = stream->codec_param.setting.frm_per_pkt; 2289 2290 /* Set stream's ptime back to 20ms. We limit minimum stream's ptime 2291 * to 20ms, otherwise DTMF will be sent every 10ms which probably is 2292 * not good. 2293 */ 2294 if (stream->codec_param.info.frm_ptime < 20) { 2295 stream->codec_param.setting.frm_per_pkt = 2; 2296 } else { 2297 stream->codec_param.setting.frm_per_pkt = 1; 2298 } 2299 afd->frame_time_usec = stream->codec_param.info.frm_ptime * 2300 stream->codec_param.setting.frm_per_pkt * 1000; 2301 2302 pjmedia_codec_modify(stream->codec, &stream->codec_param); 2303 2304 PJ_LOG(4,(stream->port.info.name.ptr, 2305 "Using experimental single encoding/decoding, f/p=%d", 2306 stream->pack_frm_per_pkt)); 2307 2308 } else { 2309 afd->frame_time_usec = stream->codec_param.info.frm_ptime * 2310 stream->codec_param.setting.frm_per_pkt * 1000; 2311 } 2312 2087 2313 stream->port.info.fmt.id = stream->codec_param.info.fmt_id; 2088 2314 if (stream->codec_param.info.fmt_id == PJMEDIA_FORMAT_L16) { 2089 2315 /* Raw format */ … … 2159 2385 } 2160 2386 2161 2387 /* Get the frame size */ 2162 stream->frame_size = stream->codec_param.info.max_bps *2163 2388 jb_frame_size = stream->codec_param.info.max_bps * 2389 stream->codec_param.info.frm_ptime / 8 / 1000; 2164 2390 if ((stream->codec_param.info.max_bps * stream->codec_param.info.frm_ptime) 2165 2391 % 8000 != 0) 2166 2392 { 2167 ++ stream->frame_size;2393 ++jb_frame_size; 2168 2394 } 2169 2395 2170 2396 /* How many consecutive PLC frames can be generated */ … … 2216 2442 2217 2443 /* Create jitter buffer */ 2218 2444 status = pjmedia_jbuf_create(pool, &stream->port.info.name, 2219 stream->frame_size, 2445 jb_frame_size, 2220 2446 stream->codec_param.info.frm_ptime, 2221 2447 jb_max, &stream->jb); 2222 2448 if (status != PJ_SUCCESS)