Ticket #486: ticket486.2.patch
File ticket486.2.patch, 11.6 KB (added by nanang, 17 years ago) |
---|
-
pjmedia/include/pjmedia/config.h
492 492 # define PJMEDIA_HAS_SRTP 1 493 493 #endif 494 494 495 /** 496 * Handle inconsitence sampling clockrate between SDP & actually used, 497 * identified codecs having this issue are G.722 and MPEG. 498 * See: 499 * - G.722 : RFC 3551 4.5.2 500 * - MPEG audio : RFC 3551 4.5.13 & RFC 3119 501 * 502 * By default it is enabled. 503 */ 504 #ifndef PJMEDIA_HANDLE_G722_MPEG_BUG 505 # define PJMEDIA_HANDLE_G722_MPEG_BUG 1 506 #endif 495 507 508 496 509 /** 497 510 * @} 498 511 */ -
pjmedia/src/pjmedia/stream.c
92 92 ptime is different than dec. 93 93 Otherwise it's NULL. */ 94 94 95 unsigned enc_samples_per_ frame;95 unsigned enc_samples_per_pkt; 96 96 unsigned enc_buf_size; /**< Encoding buffer size, in 97 97 samples. */ 98 98 unsigned enc_buf_pos; /**< First position in buf. */ … … 131 131 /* DTMF callback */ 132 132 void (*dtmf_cb)(pjmedia_stream*, void*, int); 133 133 void *dtmf_cb_user_data; 134 135 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 136 /* Handle codec with inconsistence clockrate between definition and 137 * implementation. This is possible because of error in RFC (e.g: G722) 138 * or video synchronization (MPEG audio). 139 */ 140 pj_bool_t has_g722_mpeg_bug; 141 /**< Flag to specify whether 142 normalization process 143 is needed */ 144 unsigned rtp_tx_samples_per_pkt; 145 /**< Normalized samples per packet 146 transmitted according to 147 'erroneous' definition */ 148 unsigned rtp_rx_samples_per_frame; 149 /**< Normalized samples per frame 150 received according to 151 'erroneous' definition */ 152 pj_uint32_t rtp_rx_last_ts;/**< Last received RTP timestamp 153 for timestamp checking */ 154 pj_bool_t incons_checked;/**< Flag to specify whether 155 timestamp checking is done */ 156 #endif 157 134 158 }; 135 159 136 160 … … 516 540 pjmedia_channel *channel = stream->enc; 517 541 pj_status_t status = 0; 518 542 pjmedia_frame frame_out; 519 unsigned ts_len, samples_per_frame;543 unsigned ts_len, rtp_ts_len, samples_per_frame; 520 544 void *rtphdr; 521 545 int rtphdrlen; 522 546 int inc_timestamp = 0; … … 535 559 536 560 /* Increment transmit duration */ 537 561 stream->tx_duration += ts_len; 562 rtp_ts_len = ts_len; 538 563 564 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 565 /* Handle special case for audio codec with RTP timestamp inconsistence 566 * e.g: G722, MPEG audio. 567 */ 568 if (stream->has_g722_mpeg_bug && 569 stream->rtp_tx_samples_per_pkt != stream->enc_samples_per_pkt) 570 { 571 rtp_ts_len /= stream->enc_samples_per_pkt; 572 rtp_ts_len *= stream->rtp_tx_samples_per_pkt; 573 } 574 #endif 575 539 576 /* Init frame_out buffer. */ 540 577 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 541 578 frame_out.size = 0; 542 579 543 580 /* Calculate number of samples per frame */ 544 samples_per_frame = stream->enc_samples_per_ frame;581 samples_per_frame = stream->enc_samples_per_pkt; 545 582 546 583 547 584 /* If we have DTMF digits in the queue, transmit the digits. … … 558 595 */ 559 596 status = pjmedia_rtp_encode_rtp( &channel->rtp, 560 597 stream->tx_event_pt, first, 561 frame_out.size, (first?ts_len:0), 598 frame_out.size, 599 (first ? rtp_ts_len : 0), 562 600 (const void**)&rtphdr, 563 601 &rtphdrlen); 564 602 … … 567 605 * Increment the RTP timestamp of the RTP session, for next 568 606 * RTP packets. 569 607 */ 570 inc_timestamp = PJMEDIA_DTMF_DURATION - ts_len;608 inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len; 571 609 } 572 610 573 611 /* No need to encode if this is a zero frame. … … 635 673 /* Encapsulate. */ 636 674 status = pjmedia_rtp_encode_rtp( &channel->rtp, 637 675 channel->pt, 0, 638 frame_out.size, ts_len,676 frame_out.size, rtp_ts_len, 639 677 (const void**)&rtphdr, 640 678 &rtphdrlen); 641 679 } else { … … 643 681 /* Just update RTP session's timestamp. */ 644 682 status = pjmedia_rtp_encode_rtp( &channel->rtp, 645 683 0, 0, 646 0, ts_len,684 0, rtp_ts_len, 647 685 (const void**)&rtphdr, 648 686 &rtphdrlen); 649 687 … … 724 762 pjmedia_frame tmp_zero_frame; 725 763 unsigned samples_per_frame; 726 764 727 samples_per_frame = stream->enc_samples_per_ frame;765 samples_per_frame = stream->enc_samples_per_pkt; 728 766 729 767 /* http://www.pjsip.org/trac/ticket/56: 730 768 * when input is PJMEDIA_FRAME_TYPE_NONE, feed zero PCM frame … … 801 839 /* If we still have full frame in the buffer, re-run 802 840 * rebuffer() with NULL frame. 803 841 */ 804 if (stream->enc_buf_count >= stream->enc_samples_per_ frame) {842 if (stream->enc_buf_count >= stream->enc_samples_per_pkt) { 805 843 806 844 tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE; 807 845 … … 1021 1059 enum { MAX = 16 }; 1022 1060 pj_timestamp ts; 1023 1061 unsigned i, count = MAX; 1024 unsigned samples_per_frame;1062 unsigned ts_span; 1025 1063 pjmedia_frame frames[MAX]; 1026 1064 1027 1065 /* Get the timestamp of the first sample */ … … 1041 1079 count = 0; 1042 1080 } 1043 1081 1082 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 1083 /* Check inconsistency of RTP timestamp with actual codec timestamp */ 1084 if (stream->has_g722_mpeg_bug) { 1085 if (!stream->incons_checked) { 1086 ts_span = stream->codec_param.info.frm_ptime * 1087 stream->codec_param.info.clock_rate * 1088 stream->codec_param.info.channel_cnt / 1089 1000; 1090 1091 /* Make sure the calculation applied only when 1092 * two consecutive packets have valid RTP sequence, 1093 * and no wrapped timestamp. 1094 */ 1095 if (seq_st.diff == 1 && stream->rtp_rx_last_ts && 1096 ts.u64 > stream->rtp_rx_last_ts) 1097 { 1098 stream->incons_checked = PJ_TRUE; 1099 stream->rtp_rx_samples_per_frame = 1100 (ts.u32.lo - stream->rtp_rx_last_ts) / count; 1101 1102 stream->rtp_tx_samples_per_pkt = 1103 stream->rtp_rx_samples_per_frame * 1104 stream->codec_param.setting.frm_per_pkt; 1105 ts_span = stream->rtp_rx_samples_per_frame; 1106 1107 /* Check for ptime difference on sending & receiving*/ 1108 if (stream->codec_param.info.enc_ptime) 1109 stream->rtp_tx_samples_per_pkt *= 1110 stream->codec_param.info.enc_ptime / 1111 stream->codec_param.info.frm_ptime; 1112 1113 PJ_LOG(4, (THIS_FILE, "'Problematic codec' used, " 1114 "remote samples per frame: %d", 1115 stream->rtp_rx_samples_per_frame)); 1116 } 1117 if (!channel->rtp.seq_ctrl.probation) 1118 stream->rtp_rx_last_ts = (pj_uint32_t)ts.u64; 1119 1120 } else { 1121 ts_span = stream->rtp_rx_samples_per_frame; 1122 } 1123 } else { 1124 ts_span = stream->codec_param.info.frm_ptime * 1125 stream->codec_param.info.clock_rate * 1126 stream->codec_param.info.channel_cnt / 1127 1000; 1128 } 1129 #else 1130 ts_span = stream->codec_param.info.frm_ptime * 1131 stream->codec_param.info.clock_rate * 1132 stream->codec_param.info.channel_cnt / 1133 1000; 1134 #endif 1135 1044 1136 /* 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 1137 for (i=0; i<count; ++i) { 1051 1138 unsigned ext_seq; 1052 1139 1053 ext_seq = (unsigned)(frames[i].timestamp.u64 / 1054 samples_per_frame); 1140 ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span); 1055 1141 pjmedia_jbuf_put_frame(stream->jb, frames[i].buf, 1056 1142 frames[i].size, ext_seq); 1057 1143 … … 1185 1271 name.ptr = (char*) pj_pool_alloc(pool, M); 1186 1272 name.slen = pj_ansi_snprintf(name.ptr, M, "strm%p", stream); 1187 1273 1188 1189 1274 /* Init some port-info. Some parts of the info will be set later 1190 1275 * once we have more info about the codec. 1191 1276 */ … … 1258 1343 stream->codec_param.setting.frm_per_pkt / 1259 1344 1000; 1260 1345 1261 1262 1346 /* Open the codec: */ 1263 1347 1264 1348 status = stream->codec->op->open(stream->codec, &stream->codec_param); … … 1274 1358 { 1275 1359 unsigned ptime; 1276 1360 1277 stream->enc_samples_per_ frame= stream->codec_param.info.enc_ptime *1278 1361 stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 1362 stream->port.info.clock_rate / 1000; 1279 1363 1280 1364 /* Set buffer size as twice the largest ptime value between 1281 1365 * stream's ptime, encoder ptime, or decoder ptime. … … 1298 1382 pj_pool_alloc(pool, stream->enc_buf_size * 2); 1299 1383 1300 1384 } else { 1301 stream->enc_samples_per_ frame= stream->port.info.samples_per_frame;1385 stream->enc_samples_per_pkt = stream->port.info.samples_per_frame; 1302 1386 } 1303 1387 1388 1304 1389 /* Initially disable the VAD in the stream, to help traverse NAT better */ 1305 1390 stream->vad_enabled = stream->codec_param.setting.vad; 1306 1391 if (stream->vad_enabled) { … … 1316 1401 stream->codec_param.info.frm_ptime / 1000; 1317 1402 1318 1403 1404 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 1405 stream->incons_checked = PJ_FALSE; 1406 stream->has_g722_mpeg_bug = PJ_FALSE; 1407 stream->rtp_rx_last_ts = 0; 1408 stream->rtp_tx_samples_per_pkt = stream->enc_samples_per_pkt; 1409 stream->rtp_rx_samples_per_frame = stream->port.info.samples_per_frame; 1410 1319 1411 /* Init RTCP session: */ 1320 1412 1413 /* Special case for G.722 */ 1414 if (info->fmt.pt == PJMEDIA_RTP_PT_G722) { 1415 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1416 8000, 1417 160, 1418 info->ssrc); 1419 stream->has_g722_mpeg_bug = PJ_TRUE; 1420 stream->rtp_tx_samples_per_pkt = 160 * 1421 stream->codec_param.setting.frm_per_pkt; 1422 stream->rtp_rx_samples_per_frame = 160; 1423 } else { 1424 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1425 info->fmt.clock_rate, 1426 stream->port.info.samples_per_frame, 1427 info->ssrc); 1428 } 1429 #else 1321 1430 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1322 1431 info->fmt.clock_rate, 1323 1432 stream->port.info.samples_per_frame, 1324 1433 info->ssrc); 1434 #endif 1325 1435 1326 1327 1436 /* Init jitter buffer parameters: */ 1328 1437 if (info->jb_max > 0) 1329 1438 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.enc_name = codec_info->encoding_name; 416 417 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 418 if (codec_info->pt == PJMEDIA_RTP_PT_G722) 419 rtpmap.clock_rate = 8000; 420 else 421 rtpmap.clock_rate = codec_info->clock_rate; 422 #else 415 423 rtpmap.clock_rate = codec_info->clock_rate; 416 rtpmap.enc_name = codec_info->encoding_name; 417 424 #endif 425 418 426 /* For audio codecs, rtpmap parameters denotes the number 419 427 * of channels, which can be omited if the value is 1. 420 428 */ -
pjmedia/src/pjmedia/session.c
388 388 pj_strdup(pool, &si->fmt.encoding_name, &rtpmap->enc_name); 389 389 si->fmt.clock_rate = rtpmap->clock_rate; 390 390 391 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 392 /* The session info should have the actual clock rate, because 393 * this info is used for calculationg buffer size, etc in stream */ 394 if (si->fmt.pt == PJMEDIA_RTP_PT_G722) 395 si->fmt.clock_rate = 16000; 396 #endif 397 391 398 /* For audio codecs, rtpmap parameters denotes the number of 392 399 * channels. 393 400 */