diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 3256d0ae6f..13727b7390 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -196,6 +196,9 @@ struct switch_media_bug { switch_codec_implementation_t read_impl; switch_codec_implementation_t write_impl; switch_timer_t timer; + uint32_t last_read_ts; + uint32_t last_write_ts; + switch_frame_t *ping_frame; struct switch_media_bug *next; }; diff --git a/src/switch_core_io.c b/src/switch_core_io.c index bd3d649656..6be402824e 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -658,12 +658,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi if (bp->ready && switch_test_flag(bp, SMBF_READ_PING)) { switch_mutex_lock(bp->read_mutex); + bp->ping_frame = *frame; if (bp->callback) { if (bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_PING) == SWITCH_FALSE || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) { ok = SWITCH_FALSE; } } + bp->ping_frame = NULL;; switch_mutex_unlock(bp->read_mutex); } diff --git a/src/switch_core_media_bug.c b/src/switch_core_media_bug.c index a5b50d3208..ce6f01ada8 100644 --- a/src/switch_core_media_bug.c +++ b/src/switch_core_media_bug.c @@ -117,11 +117,15 @@ SWITCH_DECLARE(void *) switch_core_media_bug_get_user_data(switch_media_bug_t *b SWITCH_DECLARE(void) switch_core_media_bug_flush(switch_media_bug_t *bug) { if (bug->raw_read_buffer) { + switch_mutex_lock(bug->read_mutex); switch_buffer_zero(bug->raw_read_buffer); + switch_mutex_unlock(bug->read_mutex); } if (bug->raw_write_buffer) { + switch_mutex_lock(bug->write_mutex); switch_buffer_zero(bug->raw_write_buffer); + switch_mutex_unlock(bug->write_mutex); } } @@ -169,7 +173,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b switch_codec_implementation_t read_impl = { 0 }; int16_t *tp; audio_buffer_header_t rh = { 0 }, wh = { 0 }; - int do_read = 0, do_write = 0; + int do_read = 0, do_write = 0, fill_read = 0, fill_write = 0; + switch_core_session_get_read_impl(bug->session, &read_impl); @@ -187,8 +192,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b return SWITCH_STATUS_FALSE; } - - frame->flags = 0; frame->datalen = 0; @@ -204,24 +207,61 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b switch_mutex_unlock(bug->write_mutex); } - if (!(do_read && do_write)) { + if ((do_read && rh.len > SWITCH_RECOMMENDED_BUFFER_SIZE) || (do_write && wh.len > SWITCH_RECOMMENDED_BUFFER_SIZE)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error!\n"); + switch_core_media_bug_flush(bug); return SWITCH_STATUS_FALSE; } + if (!((bug->last_read_ts && bug->last_write_ts) || (do_read && do_write))) { + return SWITCH_STATUS_FALSE; + } + + if (fill) { + fill_read = !do_read; + fill_write = !do_write; + } + + if (fill && fill_read && fill_write) { + return SWITCH_STATUS_FALSE; + } + + if (!((do_read || fill_read) && (do_write || fill_write))) { + return SWITCH_STATUS_FALSE; + } + if (do_read) { switch_mutex_lock(bug->read_mutex); switch_buffer_read(bug->raw_read_buffer, &rh, sizeof(rh)); + bug->last_read_ts = rh.ts; frame->datalen = (uint32_t) switch_buffer_read(bug->raw_read_buffer, frame->data, rh.len); + if (frame->datalen != rh.len) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error Reading!\n"); + switch_core_media_bug_flush(bug); + return SWITCH_STATUS_FALSE; + } + switch_mutex_unlock(bug->read_mutex); + } else if (fill_read) { + frame->datalen = bytes; + memset(frame->data, 255, frame->datalen); } if (do_write) { switch_assert(bug->raw_write_buffer); switch_mutex_lock(bug->write_mutex); switch_buffer_read(bug->raw_write_buffer, &wh, sizeof(wh)); - + bug->last_write_ts = wh.ts; datalen = (uint32_t) switch_buffer_read(bug->raw_write_buffer, bug->data, wh.len); + if (datalen != wh.len) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_ERROR, "Framing Error Writing!\n"); + switch_core_media_bug_flush(bug); + return SWITCH_STATUS_FALSE; + } switch_mutex_unlock(bug->write_mutex); + } else if (fill_write) { + datalen = bytes; + memset(bug->data, 255, datalen); } tp = bug->tmp; @@ -279,7 +319,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b switch_normalize_to_16bit(z); - *(fp + x) = (int16_t) z / 2; + *(fp + x) = (int16_t) z; } } @@ -288,6 +328,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b frame->rate = read_impl.actual_samples_per_second; frame->codec = NULL; + if (fill_read && fill_write) { + return SWITCH_STATUS_BREAK; + } + return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 2e96c8aa0b..3de9e8df89 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -1101,7 +1101,13 @@ static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, s frame.data = data; frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; - while (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && !switch_test_flag((&frame), SFF_CNG)) { + for (;;) { + switch_status_t status = switch_core_media_bug_read(bug, &frame, SWITCH_FALSE); + + if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { + break; + } + len = (switch_size_t) frame.datalen / 2; if (len && switch_core_file_write(rh->fh, data, &len) != SWITCH_STATUS_SUCCESS && rh->hangup_on_error) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error writing %s\n", rh->file); @@ -1109,6 +1115,8 @@ static switch_bool_t record_callback(switch_media_bug_t *bug, void *user_data, s switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE); return SWITCH_FALSE; } + + if (status == SWITCH_STATUS_BREAK) break; } } @@ -1163,7 +1171,7 @@ static switch_bool_t eavesdrop_callback(switch_media_bug_t *bug, void *user_data break; case SWITCH_ABC_TYPE_READ_PING: if (ep->buffer) { - if (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { + if (switch_core_media_bug_read(bug, &frame, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { switch_buffer_lock(ep->buffer); switch_buffer_zwrite(ep->buffer, frame.data, frame.datalen); switch_buffer_unlock(ep->buffer); @@ -3465,7 +3473,7 @@ static switch_bool_t speech_callback(switch_media_bug_t *bug, void *user_data, s break; case SWITCH_ABC_TYPE_READ: if (sth->ah) { - if (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { + if (switch_core_media_bug_read(bug, &frame, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { if (switch_core_asr_feed(sth->ah, frame.data, frame.datalen, &flags) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG, "Error Feeding Data\n"); return SWITCH_FALSE;