Skip to content

Commit f0123b1

Browse files
author
minhtuan1407-telnyx
committed
TEL-6986: Generate silence toward A-leg from hold path
1 parent 15cf804 commit f0123b1

2 files changed

Lines changed: 60 additions & 3 deletions

File tree

src/switch_core_media.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4324,7 +4324,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_write_frame(switch_core_sessio
43244324
if (type == SWITCH_MEDIA_TYPE_AUDIO) {
43254325
switch_media_flow_t audio_flow = switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_AUDIO);
43264326

4327-
if (audio_flow != SWITCH_MEDIA_FLOW_SENDRECV && audio_flow != SWITCH_MEDIA_FLOW_SENDONLY) {
4327+
if (!(flags & SWITCH_IO_FLAG_FORCE) && audio_flow != SWITCH_MEDIA_FLOW_SENDRECV && audio_flow != SWITCH_MEDIA_FLOW_SENDONLY) {
43284328
switch_thread_rwlock_unlock(engine->dtls_init_rwlock);
43294329
return SWITCH_STATUS_SUCCESS;
43304330
}

src/switch_ivr_bridge.c

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,15 @@ static switch_bool_t is_silence_frame(switch_frame_t *frame, int silence_thresho
400400
return is_silence;
401401
}
402402

403+
static switch_status_t write_hold_generated_silence(switch_core_session_t *session_b, switch_frame_t *silence_frame,
404+
switch_codec_implementation_t *read_impl, int silence_val, int stream_id)
405+
{
406+
switch_generate_sln_silence((int16_t *) silence_frame->data, silence_frame->samples,
407+
read_impl->number_of_channels, silence_val);
408+
409+
return switch_core_session_write_frame(session_b, silence_frame, SWITCH_IO_FLAG_FORCE, stream_id);
410+
}
411+
403412

404413
SWITCH_DECLARE(void) switch_ivr_bridge_display(switch_core_session_t *session, switch_core_session_t *peer_session)
405414
{
@@ -440,6 +449,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
440449
const char *silence_var;
441450
const char *continuous_silence_var;
442451
int silence_val = 0, bypass_media_after_bridge = 0, max_continuous_silence_ms = 0, silence_threshold = 0;
452+
int silence_codec_initialized = 0, generate_silence_on_hold = 0;
443453
const char *bridge_answer_timeout = NULL;
444454
int bridge_filter_dtmf, answer_timeout, sent_update = 0;
445455
time_t answer_limit = 0;
@@ -625,6 +635,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
625635

626636
silence_val = 0;
627637
} else {
638+
silence_codec_initialized = 1;
628639
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "Setup generated silence from %s to %s at %d\n", switch_channel_get_name(chan_a),
629640
switch_channel_get_name(chan_b), silence_val);
630641
silence_frame.codec = &silence_codec;
@@ -640,11 +651,40 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
640651
#endif
641652
}
642653

654+
if (switch_channel_var_true(chan_b, "bridge_generate_silence_on_hold")) {
655+
generate_silence_on_hold = 1;
656+
657+
if (!silence_val) {
658+
silence_val = 1400;
659+
660+
if (switch_core_codec_init(&silence_codec,
661+
"L16",
662+
NULL,
663+
NULL,
664+
read_impl.actual_samples_per_second,
665+
read_impl.microseconds_per_packet / 1000,
666+
1,
667+
SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
668+
NULL, switch_core_session_get_pool(session_a)) != SWITCH_STATUS_SUCCESS) {
669+
silence_val = 0;
670+
generate_silence_on_hold = 0;
671+
} else {
672+
silence_codec_initialized = 1;
673+
silence_frame.codec = &silence_codec;
674+
silence_frame.data = silence_data;
675+
silence_frame.buflen = sizeof(silence_data);
676+
silence_frame.datalen = read_impl.decoded_bytes_per_packet;
677+
silence_frame.samples = silence_frame.datalen / sizeof(int16_t);
678+
}
679+
}
680+
}
681+
643682
bridge_filter_dtmf = switch_true(switch_channel_get_variable(chan_a, "bridge_filter_dtmf"));
644683

645684

646685
for (;;) {
647686
int sanity = 1000;
687+
int source_held = 0, target_held = 0;
648688
switch_channel_state_t b_state;
649689
switch_status_t status;
650690
switch_event_t *event;
@@ -792,6 +832,9 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
792832

793833
switch_ivr_parse_all_messages(session_a);
794834

835+
source_held = switch_channel_test_flag(chan_a, CF_HOLD) || switch_channel_test_flag(chan_a, CF_LEG_HOLDING);
836+
target_held = switch_channel_test_flag(chan_b, CF_HOLD) || switch_channel_test_flag(chan_b, CF_LEG_HOLDING);
837+
795838
if (!inner_bridge && (switch_channel_test_flag(chan_a, CF_SUSPEND) || switch_channel_test_flag(chan_b, CF_SUSPEND))) {
796839
#if DEBUG_RTP
797840
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_NOTICE, "Audio bridge thread: #21 %p -> %p\n", (void*)session_a, (void*)session_b);
@@ -807,6 +850,15 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
807850
#endif
808851
goto end_of_bridge_loop;
809852
}
853+
854+
/* Hold may set CF_SUSPEND; protocol hold may only set CF_LEG_HOLDING.
855+
Use the held read (often SWITCH_STATUS_BREAK) only as the timer tick
856+
for generated silence, and never write toward a held peer. */
857+
if (generate_silence_on_hold && source_held && !target_held) {
858+
if (write_hold_generated_silence(session_b, &silence_frame, &read_impl, silence_val, stream_id) != SWITCH_STATUS_SUCCESS) {
859+
goto end_of_bridge_loop;
860+
}
861+
}
810862
continue;
811863
}
812864
#if DEBUG_RTP
@@ -1136,7 +1188,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
11361188
continue;
11371189
}
11381190

1139-
if (status != SWITCH_STATUS_BREAK && !switch_channel_test_flag(chan_a, CF_HOLD) && !switch_channel_test_flag(chan_b, CF_LEG_HOLDING)) {
1191+
if (status != SWITCH_STATUS_BREAK && !source_held && !target_held) {
11401192
#if DEBUG_RTP
11411193
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_NOTICE, "Audio bridge thread: write frame %p -> %p\n", (void*)session_a, (void*)session_b);
11421194
#endif
@@ -1145,6 +1197,11 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
11451197
"%s ending bridge by request from write function\n", switch_channel_get_name(chan_b));
11461198
goto end_of_bridge_loop;
11471199
}
1200+
} else if (generate_silence_on_hold && source_held && !target_held) {
1201+
/* Held reads can return SWITCH_STATUS_BREAK; treat BREAK as pacing for generated silence only. */
1202+
if (write_hold_generated_silence(session_b, &silence_frame, &read_impl, silence_val, stream_id) != SWITCH_STATUS_SUCCESS) {
1203+
goto end_of_bridge_loop;
1204+
}
11481205
}
11491206
} else {
11501207
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_a), SWITCH_LOG_DEBUG, "%s ending bridge by request from read function\n", switch_channel_get_name(chan_a));
@@ -1175,7 +1232,7 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
11751232
#endif
11761233

11771234

1178-
if (silence_val) {
1235+
if (silence_codec_initialized) {
11791236
switch_core_codec_destroy(&silence_codec);
11801237
}
11811238

0 commit comments

Comments
 (0)