Ticket #486: ticket486.patch
File ticket486.patch, 9.7 KB (added by nanang, 17 years ago) |
---|
-
pjmedia/src/pjmedia/stream.c
42 42 43 43 #define BYTES_PER_SAMPLE 2 44 44 45 #define HANDLE_G722_MPEG_BUG 46 45 47 /** 46 48 * Media channel. 47 49 */ … … 92 94 ptime is different than dec. 93 95 Otherwise it's NULL. */ 94 96 95 unsigned enc_samples_per_ frame;97 unsigned enc_samples_per_pkt; 96 98 unsigned enc_buf_size; /**< Encoding buffer size, in 97 99 samples. */ 98 100 unsigned enc_buf_pos; /**< First position in buf. */ … … 131 133 /* DTMF callback */ 132 134 void (*dtmf_cb)(pjmedia_stream*, void*, int); 133 135 void *dtmf_cb_user_data; 136 137 #ifdef HANDLE_G722_MPEG_BUG 138 /* Handle codec with inconsistence clockrate between definition and 139 * implementation. This is possible because of error in RFC (e.g: G722) 140 * or video synchronization (MPEG audio). 141 */ 142 pj_bool_t has_g722_mpeg_bug; 143 /**< Flag to specify whether 144 normalization process 145 is needed */ 146 unsigned rtp_tx_samples_per_pkt; 147 /**< Normalized samples per packet 148 transmitted according to 149 'erroneous' definition */ 150 unsigned rtp_rx_samples_per_frame; 151 /**< Normalized samples per frame 152 received according to 153 'erroneous' definition */ 154 pj_uint32_t rtp_rx_last_ts;/**< Last received RTP timestamp 155 for timestamp checking */ 156 pj_bool_t incons_checked;/**< Flag to specify whether 157 timestamp checking is done */ 158 #endif 159 134 160 }; 135 161 136 162 … … 516 542 pjmedia_channel *channel = stream->enc; 517 543 pj_status_t status = 0; 518 544 pjmedia_frame frame_out; 519 unsigned ts_len, samples_per_frame;545 unsigned ts_len, rtp_ts_len, samples_per_frame; 520 546 void *rtphdr; 521 547 int rtphdrlen; 522 548 int inc_timestamp = 0; … … 535 561 536 562 /* Increment transmit duration */ 537 563 stream->tx_duration += ts_len; 564 rtp_ts_len = ts_len; 538 565 566 #ifdef HANDLE_G722_MPEG_BUG 567 /* Handle special case for audio codec with RTP timestamp inconsistence 568 * e.g: G722, MPEG audio. 569 */ 570 if (stream->has_g722_mpeg_bug && 571 stream->rtp_tx_samples_per_pkt != stream->enc_samples_per_pkt) 572 { 573 rtp_ts_len /= stream->enc_samples_per_pkt; 574 rtp_ts_len *= stream->rtp_tx_samples_per_pkt; 575 } 576 #endif 577 539 578 /* Init frame_out buffer. */ 540 579 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 541 580 frame_out.size = 0; 542 581 543 582 /* Calculate number of samples per frame */ 544 samples_per_frame = stream->enc_samples_per_ frame;583 samples_per_frame = stream->enc_samples_per_pkt; 545 584 546 585 547 586 /* If we have DTMF digits in the queue, transmit the digits. … … 558 597 */ 559 598 status = pjmedia_rtp_encode_rtp( &channel->rtp, 560 599 stream->tx_event_pt, first, 561 frame_out.size, (first?ts_len:0), 600 frame_out.size, 601 (first ? rtp_ts_len : 0), 562 602 (const void**)&rtphdr, 563 603 &rtphdrlen); 564 604 … … 567 607 * Increment the RTP timestamp of the RTP session, for next 568 608 * RTP packets. 569 609 */ 570 inc_timestamp = PJMEDIA_DTMF_DURATION - ts_len;610 inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len; 571 611 } 572 612 573 613 /* No need to encode if this is a zero frame. … … 635 675 /* Encapsulate. */ 636 676 status = pjmedia_rtp_encode_rtp( &channel->rtp, 637 677 channel->pt, 0, 638 frame_out.size, ts_len,678 frame_out.size, rtp_ts_len, 639 679 (const void**)&rtphdr, 640 680 &rtphdrlen); 641 681 } else { … … 643 683 /* Just update RTP session's timestamp. */ 644 684 status = pjmedia_rtp_encode_rtp( &channel->rtp, 645 685 0, 0, 646 0, ts_len,686 0, rtp_ts_len, 647 687 (const void**)&rtphdr, 648 688 &rtphdrlen); 649 689 … … 724 764 pjmedia_frame tmp_zero_frame; 725 765 unsigned samples_per_frame; 726 766 727 samples_per_frame = stream->enc_samples_per_ frame;767 samples_per_frame = stream->enc_samples_per_pkt; 728 768 729 769 /* http://www.pjsip.org/trac/ticket/56: 730 770 * when input is PJMEDIA_FRAME_TYPE_NONE, feed zero PCM frame … … 801 841 /* If we still have full frame in the buffer, re-run 802 842 * rebuffer() with NULL frame. 803 843 */ 804 if (stream->enc_buf_count >= stream->enc_samples_per_ frame) {844 if (stream->enc_buf_count >= stream->enc_samples_per_pkt) { 805 845 806 846 tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE; 807 847 … … 1021 1061 enum { MAX = 16 }; 1022 1062 pj_timestamp ts; 1023 1063 unsigned i, count = MAX; 1024 unsigned samples_per_frame;1064 unsigned ts_span; 1025 1065 pjmedia_frame frames[MAX]; 1026 1066 1027 1067 /* Get the timestamp of the first sample */ … … 1041 1081 count = 0; 1042 1082 } 1043 1083 1084 #ifdef HANDLE_G722_MPEG_BUG 1085 /* Check inconsistency of RTP timestamp with actual codec timestamp */ 1086 if (stream->has_g722_mpeg_bug) { 1087 if (!stream->incons_checked) { 1088 ts_span = stream->codec_param.info.frm_ptime * 1089 stream->codec_param.info.clock_rate * 1090 stream->codec_param.info.channel_cnt / 1091 1000; 1092 1093 /* Make sure the calculation applied only when 1094 * two consecutive packets have valid RTP sequence, 1095 * and no wrapped timestamp. 1096 */ 1097 if (seq_st.diff == 1 && stream->rtp_rx_last_ts && 1098 ts.u64 > stream->rtp_rx_last_ts) 1099 { 1100 stream->incons_checked = PJ_TRUE; 1101 stream->rtp_rx_samples_per_frame = 1102 (ts.u32.lo - stream->rtp_rx_last_ts) / count; 1103 1104 if ((ts.u64 - stream->rtp_rx_last_ts)/count != ts_span) 1105 { 1106 stream->rtp_tx_samples_per_pkt = 1107 stream->rtp_rx_samples_per_frame * 1108 stream->codec_param.info.enc_ptime / 1109 stream->codec_param.info.frm_ptime * 1110 stream->codec_param.setting.frm_per_pkt; 1111 ts_span = stream->rtp_rx_samples_per_frame; 1112 } 1113 } 1114 stream->rtp_rx_last_ts = (pj_uint32_t)ts.u64; 1115 } else { 1116 ts_span = stream->rtp_rx_samples_per_frame; 1117 } 1118 } else { 1119 ts_span = stream->codec_param.info.frm_ptime * 1120 stream->codec_param.info.clock_rate * 1121 stream->codec_param.info.channel_cnt / 1122 1000; 1123 } 1124 #else 1125 ts_span = stream->codec_param.info.frm_ptime * 1126 stream->codec_param.info.clock_rate * 1127 stream->codec_param.info.channel_cnt / 1128 1000; 1129 #endif 1130 1044 1131 /* Put each frame to jitter buffer. */ 1045 samples_per_frame = stream->codec_param.info.frm_ptime *1046 stream->codec_param.info.clock_rate *1047 stream->codec_param.info.channel_cnt /1048 1000;1049 1050 1132 for (i=0; i<count; ++i) { 1051 1133 unsigned ext_seq; 1052 1134 1053 ext_seq = (unsigned)(frames[i].timestamp.u64 / 1054 samples_per_frame); 1135 ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span); 1055 1136 pjmedia_jbuf_put_frame(stream->jb, frames[i].buf, 1056 1137 frames[i].size, ext_seq); 1057 1138 … … 1258 1339 stream->codec_param.setting.frm_per_pkt / 1259 1340 1000; 1260 1341 1261 1262 1342 /* Open the codec: */ 1263 1343 1264 1344 status = stream->codec->op->open(stream->codec, &stream->codec_param); … … 1274 1354 { 1275 1355 unsigned ptime; 1276 1356 1277 stream->enc_samples_per_ frame= stream->codec_param.info.enc_ptime *1278 1357 stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 1358 stream->port.info.clock_rate / 1000; 1279 1359 1280 1360 /* Set buffer size as twice the largest ptime value between 1281 1361 * stream's ptime, encoder ptime, or decoder ptime. … … 1298 1378 pj_pool_alloc(pool, stream->enc_buf_size * 2); 1299 1379 1300 1380 } else { 1301 stream->enc_samples_per_ frame= stream->port.info.samples_per_frame;1381 stream->enc_samples_per_pkt = stream->port.info.samples_per_frame; 1302 1382 } 1303 1383 1384 #ifdef HANDLE_G722_MPEG_BUG 1385 stream->rtp_tx_samples_per_pkt = stream->enc_samples_per_pkt; 1386 stream->rtp_rx_samples_per_frame = 0; 1387 stream->incons_checked = PJ_FALSE; 1388 stream->has_g722_mpeg_bug = PJ_FALSE; 1389 stream->rtp_rx_last_ts = 0; 1390 #endif 1391 1304 1392 /* Initially disable the VAD in the stream, to help traverse NAT better */ 1305 1393 stream->vad_enabled = stream->codec_param.setting.vad; 1306 1394 if (stream->vad_enabled) { … … 1318 1406 1319 1407 /* Init RTCP session: */ 1320 1408 1409 #ifdef HANDLE_G722_MPEG_BUG 1410 /* Special case for G.722 */ 1411 if (info->fmt.pt == PJMEDIA_RTP_PT_G722) { 1412 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1413 8000, 1414 160, 1415 info->ssrc); 1416 stream->has_g722_mpeg_bug = PJ_TRUE; 1417 } 1418 else { 1419 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1420 info->fmt.clock_rate, 1421 stream->port.info.samples_per_frame, 1422 info->ssrc); 1423 } 1424 #else 1321 1425 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1322 1426 info->fmt.clock_rate, 1323 1427 stream->port.info.samples_per_frame, 1324 1428 info->ssrc); 1429 #endif 1325 1430 1326 1327 1431 /* Init jitter buffer parameters: */ 1328 1432 if (info->jb_max > 0) 1329 1433 jb_max = info->jb_max; -
pjmedia/src/pjmedia/endpoint.c
412 412 fmt->slen = pj_utoa(codec_info->pt, fmt->ptr); 413 413 414 414 rtpmap.pt = *fmt; 415 rtpmap.clock_rate = codec_info->clock_rate;416 415 rtpmap.enc_name = codec_info->encoding_name; 417 416 417 /* RFC 3551 Section 4.5.2: 418 * Even though the actual sampling rate for G.722 audio is 16,000 Hz, 419 * the RTP clock rate for the G722 payload format is 8,000 Hz because 420 * that value was erroneously assigned in RFC 1890 and must remain 421 * unchanged for backward compatibility. The octet rate or sample-pair 422 * rate is 8,000 Hz. 423 */ 424 if (codec_info->pt == PJMEDIA_RTP_PT_G722) 425 rtpmap.clock_rate = 8000; 426 else 427 rtpmap.clock_rate = codec_info->clock_rate; 428 418 429 /* For audio codecs, rtpmap parameters denotes the number 419 430 * of channels, which can be omited if the value is 1. 420 431 */