try to improve autoflush and other silly audio glitches from edge cases and help FSCORE-416
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14800 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
56a8eb4091
commit
7392fa5807
|
@ -112,6 +112,8 @@ SWITCH_DECLARE(switch_port_t) switch_rtp_set_end_port(switch_port_t port);
|
||||||
SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(const char *ip);
|
SWITCH_DECLARE(switch_port_t) switch_rtp_request_port(const char *ip);
|
||||||
SWITCH_DECLARE(void) switch_rtp_release_port(const char *ip, switch_port_t port);
|
SWITCH_DECLARE(void) switch_rtp_release_port(const char *ip, switch_port_t port);
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_rtp_set_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval);
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_rtp_change_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval);
|
SWITCH_DECLARE(switch_status_t) switch_rtp_change_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval);
|
||||||
/*!
|
/*!
|
||||||
\brief create a new RTP session handle
|
\brief create a new RTP session handle
|
||||||
|
@ -248,13 +250,6 @@ SWITCH_DECLARE(void) switch_rtp_clear_flag(switch_rtp_t *rtp_session, switch_rtp
|
||||||
*/
|
*/
|
||||||
SWITCH_DECLARE(switch_socket_t *) switch_rtp_get_rtp_socket(switch_rtp_t *rtp_session);
|
SWITCH_DECLARE(switch_socket_t *) switch_rtp_get_rtp_socket(switch_rtp_t *rtp_session);
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief Set the default samples per interval for a given RTP session
|
|
||||||
\param rtp_session the RTP session to set the samples per interval on
|
|
||||||
\param samples_per_interval the new default samples per interval
|
|
||||||
*/
|
|
||||||
SWITCH_DECLARE(void) switch_rtp_set_default_samples_per_interval(switch_rtp_t *rtp_session, uint32_t samples_per_interval);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Get the default samples per interval for a given RTP session
|
\brief Get the default samples per interval for a given RTP session
|
||||||
\param rtp_session the RTP session to get the samples per interval from
|
\param rtp_session the RTP session to get the samples per interval from
|
||||||
|
|
|
@ -2076,7 +2076,9 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
|
||||||
|
|
||||||
if (switch_rtp_ready(tech_pvt->rtp_session)) {
|
if (switch_rtp_ready(tech_pvt->rtp_session)) {
|
||||||
switch_assert(tech_pvt->read_codec.implementation);
|
switch_assert(tech_pvt->read_codec.implementation);
|
||||||
switch_rtp_set_default_samples_per_interval(tech_pvt->rtp_session, tech_pvt->read_impl.samples_per_packet);
|
switch_rtp_set_interval(tech_pvt->rtp_session,
|
||||||
|
tech_pvt->write_codec.implementation->microseconds_per_packet,
|
||||||
|
tech_pvt->read_impl.samples_per_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
tech_pvt->read_frame.rate = tech_pvt->rm_rate;
|
tech_pvt->read_frame.rate = tech_pvt->rm_rate;
|
||||||
|
|
|
@ -402,6 +402,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi
|
||||||
(uint32_t) bytes, (uint32_t) (*frame)->datalen);
|
(uint32_t) bytes, (uint32_t) (*frame)->datalen);
|
||||||
switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0);
|
switch_buffer_create_dynamic(&session->raw_read_buffer, bytes * SWITCH_BUFFER_BLOCK_FRAMES, bytes * SWITCH_BUFFER_START_FRAMES, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) {
|
if (!switch_buffer_write(session->raw_read_buffer, read_frame->data, read_frame->datalen)) {
|
||||||
status = SWITCH_STATUS_MEMERR;
|
status = SWITCH_STATUS_MEMERR;
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -883,10 +884,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||||
status = perform_write(session, write_frame, flags, stream_id);
|
status = perform_write(session, write_frame, flags, stream_id);
|
||||||
goto error;
|
goto error;
|
||||||
} else {
|
} else {
|
||||||
switch_size_t used;
|
|
||||||
uint32_t bytes;
|
|
||||||
switch_size_t frames;
|
|
||||||
|
|
||||||
if (!session->raw_write_buffer) {
|
if (!session->raw_write_buffer) {
|
||||||
switch_size_t bytes_per_packet = session->write_impl.decoded_bytes_per_packet;
|
switch_size_t bytes_per_packet = session->write_impl.decoded_bytes_per_packet;
|
||||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
|
||||||
|
@ -905,22 +902,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||||
status = SWITCH_STATUS_MEMERR; goto error;
|
status = SWITCH_STATUS_MEMERR; goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
used = switch_buffer_inuse(session->raw_write_buffer);
|
|
||||||
bytes = session->write_impl.decoded_bytes_per_packet;
|
|
||||||
frames = (used / bytes);
|
|
||||||
|
|
||||||
status = SWITCH_STATUS_SUCCESS;
|
status = SWITCH_STATUS_SUCCESS;
|
||||||
if (!frames) {
|
|
||||||
goto error;
|
while(switch_buffer_inuse(session->raw_write_buffer) >= session->write_impl.decoded_bytes_per_packet) {
|
||||||
} else {
|
int rate;
|
||||||
switch_size_t x;
|
|
||||||
for (x = 0; x < frames; x++) {
|
|
||||||
if (switch_channel_down(session->channel) || !session->raw_write_buffer) {
|
if (switch_channel_down(session->channel) || !session->raw_write_buffer) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if ((session->raw_write_frame.datalen = (uint32_t)
|
if ((session->raw_write_frame.datalen = (uint32_t)
|
||||||
switch_buffer_read(session->raw_write_buffer, session->raw_write_frame.data, bytes)) != 0) {
|
switch_buffer_read(session->raw_write_buffer, session->raw_write_frame.data, session->write_impl.decoded_bytes_per_packet)) == 0) {
|
||||||
int rate;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
enc_frame = &session->raw_write_frame;
|
enc_frame = &session->raw_write_frame;
|
||||||
session->raw_write_frame.rate = session->write_impl.actual_samples_per_second;
|
session->raw_write_frame.rate = session->write_impl.actual_samples_per_second;
|
||||||
session->enc_write_frame.datalen = session->enc_write_frame.buflen;
|
session->enc_write_frame.datalen = session->enc_write_frame.buflen;
|
||||||
|
@ -943,8 +937,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||||
&session->enc_write_frame.rate, &flag);
|
&session->enc_write_frame.rate, &flag);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case SWITCH_STATUS_RESAMPLE:
|
case SWITCH_STATUS_RESAMPLE:
|
||||||
resample++;
|
resample++;
|
||||||
|
@ -1033,12 +1025,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||||
if ((status = perform_write(session, write_frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
|
if ((status = perform_write(session, write_frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
|
@ -1047,12 +1043,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_write) {
|
if (do_write) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
status = perform_write(session, write_frame, flags, stream_id);
|
status = perform_write(session, write_frame, flags, stream_id);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -182,6 +182,7 @@ struct switch_rtp {
|
||||||
char *remote_host_str;
|
char *remote_host_str;
|
||||||
switch_time_t last_stun;
|
switch_time_t last_stun;
|
||||||
uint32_t samples_per_interval;
|
uint32_t samples_per_interval;
|
||||||
|
uint32_t samples_per_second;
|
||||||
uint32_t conf_samples_per_interval;
|
uint32_t conf_samples_per_interval;
|
||||||
uint32_t rsamples_per_interval;
|
uint32_t rsamples_per_interval;
|
||||||
uint32_t ms_per_packet;
|
uint32_t ms_per_packet;
|
||||||
|
@ -213,6 +214,7 @@ struct switch_rtp {
|
||||||
switch_rtp_bug_flag_t rtp_bugs;
|
switch_rtp_bug_flag_t rtp_bugs;
|
||||||
switch_rtp_stats_t stats;
|
switch_rtp_stats_t stats;
|
||||||
int hot_hits;
|
int hot_hits;
|
||||||
|
int sync_packets;
|
||||||
|
|
||||||
#ifdef ENABLE_ZRTP
|
#ifdef ENABLE_ZRTP
|
||||||
zrtp_session_t *zrtp_session;
|
zrtp_session_t *zrtp_session;
|
||||||
|
@ -1038,11 +1040,20 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_add_crypto_key(switch_rtp_t *rtp_sess
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(switch_status_t) switch_rtp_change_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval)
|
SWITCH_DECLARE(switch_status_t) switch_rtp_set_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval)
|
||||||
{
|
{
|
||||||
rtp_session->ms_per_packet = ms_per_packet;
|
rtp_session->ms_per_packet = ms_per_packet;
|
||||||
rtp_session->samples_per_interval = rtp_session->conf_samples_per_interval = samples_per_interval;
|
rtp_session->samples_per_interval = rtp_session->conf_samples_per_interval = samples_per_interval;
|
||||||
rtp_session->missed_count = 0;
|
rtp_session->missed_count = 0;
|
||||||
|
rtp_session->samples_per_second = (uint32_t)((double)(1000.0f / (double)(rtp_session->ms_per_packet / 1000)) * (double)rtp_session->samples_per_interval);
|
||||||
|
|
||||||
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWITCH_DECLARE(switch_status_t) switch_rtp_change_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch_rtp_set_interval(rtp_session, ms_per_packet, samples_per_interval);
|
||||||
|
|
||||||
if (rtp_session->timer_name) {
|
if (rtp_session->timer_name) {
|
||||||
if (rtp_session->timer.timer_interface) {
|
if (rtp_session->timer.timer_interface) {
|
||||||
|
@ -1123,8 +1134,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
||||||
rtp_session->recv_msg.header.cc = 0;
|
rtp_session->recv_msg.header.cc = 0;
|
||||||
|
|
||||||
rtp_session->payload = payload;
|
rtp_session->payload = payload;
|
||||||
rtp_session->ms_per_packet = ms_per_packet;
|
|
||||||
rtp_session->samples_per_interval = rtp_session->conf_samples_per_interval = samples_per_interval;
|
switch_rtp_set_interval(rtp_session, ms_per_packet, samples_per_interval);
|
||||||
|
rtp_session->conf_samples_per_interval = samples_per_interval;
|
||||||
|
|
||||||
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) && switch_strlen_zero(timer_name)) {
|
if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER) && switch_strlen_zero(timer_name)) {
|
||||||
timer_name = "soft";
|
timer_name = "soft";
|
||||||
|
@ -1490,11 +1502,6 @@ SWITCH_DECLARE(switch_socket_t *) switch_rtp_get_rtp_socket(switch_rtp_t *rtp_se
|
||||||
return rtp_session->sock_input;
|
return rtp_session->sock_input;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_DECLARE(void) switch_rtp_set_default_samples_per_interval(switch_rtp_t *rtp_session, uint32_t samples_per_interval)
|
|
||||||
{
|
|
||||||
rtp_session->samples_per_interval = samples_per_interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
SWITCH_DECLARE(uint32_t) switch_rtp_get_default_samples_per_interval(switch_rtp_t *rtp_session)
|
SWITCH_DECLARE(uint32_t) switch_rtp_get_default_samples_per_interval(switch_rtp_t *rtp_session)
|
||||||
{
|
{
|
||||||
return rtp_session->samples_per_interval;
|
return rtp_session->samples_per_interval;
|
||||||
|
@ -1783,7 +1790,9 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||||
if ((switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTOFLUSH) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_STICKY_FLUSH)) &&
|
if ((switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTOFLUSH) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_STICKY_FLUSH)) &&
|
||||||
rtp_session->read_pollfd) {
|
rtp_session->read_pollfd) {
|
||||||
if (switch_poll(rtp_session->read_pollfd, 1, &fdr, 1) == SWITCH_STATUS_SUCCESS) {
|
if (switch_poll(rtp_session->read_pollfd, 1, &fdr, 1) == SWITCH_STATUS_SUCCESS) {
|
||||||
if (++rtp_session->hot_hits >= 10) {
|
rtp_session->hot_hits += rtp_session->samples_per_interval;
|
||||||
|
|
||||||
|
if (rtp_session->hot_hits >= rtp_session->samples_per_second * 60) {
|
||||||
hot_socket = 1;
|
hot_socket = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1792,8 +1801,17 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hot_socket) {
|
if (hot_socket) {
|
||||||
|
rtp_session->sync_packets++;
|
||||||
switch_core_timer_sync(&rtp_session->timer);
|
switch_core_timer_sync(&rtp_session->timer);
|
||||||
} else {
|
} else {
|
||||||
|
if (rtp_session->sync_packets) {
|
||||||
|
#if 0
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||||
|
"Auto-Flush catching up %d packets (%d)ms.\n",
|
||||||
|
rtp_session->sync_packets, rtp_session->ms_per_packet * rtp_session->sync_packets);
|
||||||
|
#endif
|
||||||
|
rtp_session->sync_packets = 0;
|
||||||
|
}
|
||||||
switch_core_timer_next(&rtp_session->timer);
|
switch_core_timer_next(&rtp_session->timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2440,6 +2458,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||||
rtp_session->ts = (uint32_t) timestamp;
|
rtp_session->ts = (uint32_t) timestamp;
|
||||||
} else if (rtp_session->timer.timer_interface) {
|
} else if (rtp_session->timer.timer_interface) {
|
||||||
rtp_session->ts = rtp_session->timer.samplecount;
|
rtp_session->ts = rtp_session->timer.samplecount;
|
||||||
|
|
||||||
if (rtp_session->ts <= rtp_session->last_write_ts) {
|
if (rtp_session->ts <= rtp_session->last_write_ts) {
|
||||||
rtp_session->ts = rtp_session->last_write_ts + rtp_session->samples_per_interval;
|
rtp_session->ts = rtp_session->last_write_ts + rtp_session->samples_per_interval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,8 +307,8 @@ static switch_status_t timer_sync(switch_timer_t *timer)
|
||||||
|
|
||||||
/* apply timestamp */
|
/* apply timestamp */
|
||||||
if (timer_step(timer) == SWITCH_STATUS_SUCCESS) {
|
if (timer_step(timer) == SWITCH_STATUS_SUCCESS) {
|
||||||
/* push the reference into the future 2 more intervals to prevent collision */
|
/* push the reference into the future to prevent collision */
|
||||||
private_info->reference += 2;
|
private_info->reference++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SWITCH_STATUS_SUCCESS;
|
return SWITCH_STATUS_SUCCESS;
|
||||||
|
|
Loading…
Reference in New Issue