Ticket #486: ticket486.3.patch
File ticket486.3.patch, 11.5 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 unsigned rtp_rx_check_cnt; 155 /**< Counter of remote timestamp 156 checking */ 157 #endif 158 134 159 }; 135 160 136 161 … … 521 546 pjmedia_channel *channel = stream->enc; 522 547 pj_status_t status = 0; 523 548 pjmedia_frame frame_out; 524 unsigned ts_len, samples_per_frame;549 unsigned ts_len, rtp_ts_len, samples_per_frame; 525 550 void *rtphdr; 526 551 int rtphdrlen; 527 552 int inc_timestamp = 0; … … 541 566 /* Increment transmit duration */ 542 567 stream->tx_duration += ts_len; 543 568 569 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 570 /* Handle special case for audio codec with RTP timestamp inconsistence 571 * e.g: G722, MPEG audio. 572 */ 573 if (stream->has_g722_mpeg_bug) 574 rtp_ts_len = stream->rtp_tx_samples_per_pkt; 575 else 576 rtp_ts_len = ts_len; 577 #else 578 rtp_ts_len = ts_len; 579 #endif 580 544 581 /* Init frame_out buffer. */ 545 582 frame_out.buf = ((char*)channel->out_pkt) + sizeof(pjmedia_rtp_hdr); 546 583 frame_out.size = 0; 547 584 548 585 /* Calculate number of samples per frame */ 549 samples_per_frame = stream->enc_samples_per_ frame;586 samples_per_frame = stream->enc_samples_per_pkt; 550 587 551 588 552 589 /* If we have DTMF digits in the queue, transmit the digits. … … 563 600 */ 564 601 status = pjmedia_rtp_encode_rtp( &channel->rtp, 565 602 stream->tx_event_pt, first, 566 frame_out.size, (first?ts_len:0), 603 frame_out.size, 604 (first ? rtp_ts_len : 0), 567 605 (const void**)&rtphdr, 568 606 &rtphdrlen); 569 607 … … 572 610 * Increment the RTP timestamp of the RTP session, for next 573 611 * RTP packets. 574 612 */ 575 inc_timestamp = PJMEDIA_DTMF_DURATION - ts_len;613 inc_timestamp = PJMEDIA_DTMF_DURATION - rtp_ts_len; 576 614 } 577 615 578 616 /* No need to encode if this is a zero frame. … … 640 678 /* Encapsulate. */ 641 679 status = pjmedia_rtp_encode_rtp( &channel->rtp, 642 680 channel->pt, 0, 643 frame_out.size, ts_len,681 frame_out.size, rtp_ts_len, 644 682 (const void**)&rtphdr, 645 683 &rtphdrlen); 646 684 } else { … … 648 686 /* Just update RTP session's timestamp. */ 649 687 status = pjmedia_rtp_encode_rtp( &channel->rtp, 650 688 0, 0, 651 0, ts_len,689 0, rtp_ts_len, 652 690 (const void**)&rtphdr, 653 691 &rtphdrlen); 654 692 … … 729 767 pjmedia_frame tmp_zero_frame; 730 768 unsigned samples_per_frame; 731 769 732 samples_per_frame = stream->enc_samples_per_ frame;770 samples_per_frame = stream->enc_samples_per_pkt; 733 771 734 772 /* http://www.pjsip.org/trac/ticket/56: 735 773 * when input is PJMEDIA_FRAME_TYPE_NONE, feed zero PCM frame … … 806 844 /* If we still have full frame in the buffer, re-run 807 845 * rebuffer() with NULL frame. 808 846 */ 809 if (stream->enc_buf_count >= stream->enc_samples_per_ frame) {847 if (stream->enc_buf_count >= stream->enc_samples_per_pkt) { 810 848 811 849 tmp_rebuffer_frame.type = PJMEDIA_FRAME_TYPE_NONE; 812 850 … … 1026 1064 enum { MAX = 16 }; 1027 1065 pj_timestamp ts; 1028 1066 unsigned i, count = MAX; 1029 unsigned samples_per_frame;1067 unsigned ts_span; 1030 1068 pjmedia_frame frames[MAX]; 1031 1069 1032 1070 /* Get the timestamp of the first sample */ … … 1046 1084 count = 0; 1047 1085 } 1048 1086 1087 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 1088 /* Check inconsistency of RTP timestamp with actual codec timestamp */ 1089 if (stream->has_g722_mpeg_bug) { 1090 if (stream->rtp_rx_check_cnt) { 1091 /* Make sure the detection performed only on two consecutive 1092 * packets with valid RTP sequence and no wrapped timestamp. 1093 */ 1094 if (seq_st.diff == 1 && stream->rtp_rx_last_ts && 1095 ts.u64 > stream->rtp_rx_last_ts) 1096 { 1097 unsigned peer_frm_ts_diff; 1098 1099 peer_frm_ts_diff = 1100 ((pj_uint32_t)ts.u64-stream->rtp_rx_last_ts) / count; 1101 1102 /* Possibilities remote's samples per frame for G.722 1103 * are only 160 and 320, this validation is needed 1104 * to avoid wrong decision because of silence frames. 1105 */ 1106 if (stream->codec_param.info.pt == PJMEDIA_RTP_PT_G722 && 1107 (peer_frm_ts_diff == stream->port.info.samples_per_frame 1108 || peer_frm_ts_diff == 1109 stream->port.info.samples_per_frame/2)) 1110 { 1111 if (peer_frm_ts_diff < stream->rtp_rx_samples_per_frame) 1112 stream->rtp_rx_samples_per_frame = peer_frm_ts_diff; 1113 1114 if (--stream->rtp_rx_check_cnt == 0) { 1115 PJ_LOG(4, (THIS_FILE, "G722 codec used, remote" 1116 " samples per frame detected = %d", 1117 stream->rtp_rx_samples_per_frame)); 1118 1119 /* Reset jitter buffer once detection done */ 1120 pjmedia_jbuf_reset(stream->jb); 1121 } 1122 } 1123 } 1124 1125 stream->rtp_rx_last_ts = (pj_uint32_t)ts.u64; 1126 } 1127 1128 ts_span = stream->rtp_rx_samples_per_frame; 1129 1130 } else { 1131 ts_span = stream->codec_param.info.frm_ptime * 1132 stream->codec_param.info.clock_rate * 1133 stream->codec_param.info.channel_cnt / 1134 1000; 1135 } 1136 #else 1137 ts_span = stream->codec_param.info.frm_ptime * 1138 stream->codec_param.info.clock_rate * 1139 stream->codec_param.info.channel_cnt / 1140 1000; 1141 #endif 1142 1049 1143 /* Put each frame to jitter buffer. */ 1050 samples_per_frame = stream->codec_param.info.frm_ptime *1051 stream->codec_param.info.clock_rate *1052 stream->codec_param.info.channel_cnt /1053 1000;1054 1055 1144 for (i=0; i<count; ++i) { 1056 1145 unsigned ext_seq; 1057 1146 1058 ext_seq = (unsigned)(frames[i].timestamp.u64 / 1059 samples_per_frame); 1147 ext_seq = (unsigned)(frames[i].timestamp.u64 / ts_span); 1060 1148 pjmedia_jbuf_put_frame(stream->jb, frames[i].buf, 1061 1149 frames[i].size, ext_seq); 1062 1150 … … 1190 1278 name.ptr = (char*) pj_pool_alloc(pool, M); 1191 1279 name.slen = pj_ansi_snprintf(name.ptr, M, "strm%p", stream); 1192 1280 1193 1194 1281 /* Init some port-info. Some parts of the info will be set later 1195 1282 * once we have more info about the codec. 1196 1283 */ … … 1263 1350 stream->codec_param.setting.frm_per_pkt / 1264 1351 1000; 1265 1352 1266 1267 1353 /* Open the codec: */ 1268 1354 1269 1355 status = stream->codec->op->open(stream->codec, &stream->codec_param); … … 1279 1365 { 1280 1366 unsigned ptime; 1281 1367 1282 stream->enc_samples_per_ frame= stream->codec_param.info.enc_ptime *1283 1368 stream->enc_samples_per_pkt = stream->codec_param.info.enc_ptime * 1369 stream->port.info.clock_rate / 1000; 1284 1370 1285 1371 /* Set buffer size as twice the largest ptime value between 1286 1372 * stream's ptime, encoder ptime, or decoder ptime. … … 1303 1389 pj_pool_alloc(pool, stream->enc_buf_size * 2); 1304 1390 1305 1391 } else { 1306 stream->enc_samples_per_ frame= stream->port.info.samples_per_frame;1392 stream->enc_samples_per_pkt = stream->port.info.samples_per_frame; 1307 1393 } 1308 1394 1395 1309 1396 /* Initially disable the VAD in the stream, to help traverse NAT better */ 1310 1397 stream->vad_enabled = stream->codec_param.setting.vad; 1311 1398 if (stream->vad_enabled) { … … 1321 1408 stream->codec_param.info.frm_ptime / 1000; 1322 1409 1323 1410 1411 #if defined(PJMEDIA_HANDLE_G722_MPEG_BUG) && (PJMEDIA_HANDLE_G722_MPEG_BUG != 0) 1412 stream->rtp_rx_check_cnt = 5; 1413 stream->has_g722_mpeg_bug = PJ_FALSE; 1414 stream->rtp_rx_last_ts = 0; 1415 stream->rtp_tx_samples_per_pkt = stream->enc_samples_per_pkt; 1416 stream->rtp_rx_samples_per_frame = stream->port.info.samples_per_frame; 1417 1324 1418 /* Init RTCP session: */ 1325 1419 1420 /* Special case for G.722 */ 1421 if (info->fmt.pt == PJMEDIA_RTP_PT_G722) { 1422 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1423 8000, 1424 160, 1425 info->ssrc); 1426 stream->has_g722_mpeg_bug = PJ_TRUE; 1427 /* RTP clock rate = 1/2 real clock rate */ 1428 stream->rtp_tx_samples_per_pkt /= 2; 1429 } else { 1430 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1431 info->fmt.clock_rate, 1432 stream->port.info.samples_per_frame, 1433 info->ssrc); 1434 } 1435 #else 1326 1436 pjmedia_rtcp_init(&stream->rtcp, stream->port.info.name.ptr, 1327 1437 info->fmt.clock_rate, 1328 1438 stream->port.info.samples_per_frame, 1329 1439 info->ssrc); 1440 #endif 1330 1441 1331 1332 1442 /* Init jitter buffer parameters: */ 1333 1443 if (info->jb_max > 0) 1334 1444 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 */