diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 3c4a43bb4..5aef55baf 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1019,6 +1019,9 @@ static void call_ng_flags_flags(sdp_ng_flags *out, str *s, helper_arg dummy) { case CSH_LOOKUP("block-DTMF"): out->block_dtmf = 1; break; + case CSH_LOOKUP("block-egress"): + out->block_egress = 1; + break; case CSH_LOOKUP("block-short"): case CSH_LOOKUP("block-shorts"): case CSH_LOOKUP("block-short-packets"): @@ -2412,6 +2415,7 @@ static void ng_stats_media(bencode_item_t *list, const struct call_media *m, BF_M("legacy OSRTP", LEGACY_OSRTP); BF_M("reverse legacy OSRTP", LEGACY_OSRTP_REV); BF_M("transcoding", TRANSCODING); + BF_M("block egress", BLOCK_EGRESS); stats: for (auto_iter(l, m->streams.head); l; l = l->next) { @@ -3380,6 +3384,7 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) { media_player_opts_t opts = MPO( .repeat = flags.repeat_times, .start_pos = flags.start_pos, + .block_egress = !!flags.block_egress, ); if (flags.file.len) { diff --git a/daemon/codec.c b/daemon/codec.c index a9506b483..917aed1f8 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -1700,7 +1700,7 @@ static void codec_add_raw_packet_dup(struct media_packet *mp, unsigned int clock } #endif static bool handler_silence_block(struct codec_handler *h, struct media_packet *mp) { - if (CALL_ISSET(mp->call, BLOCK_MEDIA) || ML_ISSET(mp->media->monologue, BLOCK_MEDIA) || mp->sink.attrs.block_media) + if (CALL_ISSET(mp->call, BLOCK_MEDIA) || ML_ISSET(mp->media->monologue, BLOCK_MEDIA) || mp->sink.attrs.block_media || MEDIA_ISSET(mp->media_out, BLOCK_EGRESS)) return false; if (CALL_ISSET(mp->call, SILENCE_MEDIA) || ML_ISSET(mp->media->monologue, SILENCE_MEDIA) || mp->sink.attrs.silence_media) { if (h->source_pt.codec_def && h->source_pt.codec_def->silence_pattern.len) { diff --git a/daemon/media_player.c b/daemon/media_player.c index 9a9a9e3f8..2221d2900 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -122,6 +122,9 @@ static void media_player_shutdown(struct media_player *mp) { mp->ssrc_out->parent->seq_diff -= num; } + if (mp->opts.block_egress) + MEDIA_CLEAR(mp->media, BLOCK_EGRESS); + mp->media = NULL; media_player_coder_shutdown(&mp->coder); @@ -942,6 +945,9 @@ static void media_player_play_start(struct media_player *mp, const rtp_payload_t if (__ensure_codec_handler(mp, dst_pt)) return; + if (mp->opts.block_egress) + MEDIA_SET(mp->media, BLOCK_EGRESS); + if (media_player_cache_entry_init(mp, dst_pt)) return; @@ -1284,6 +1290,9 @@ static void media_player_run(void *ptr) { mp->next_run.tv_sec = 0; + if (mp->opts.block_egress) + MEDIA_CLEAR(mp->media, BLOCK_EGRESS); + codec_update_all_source_handlers(mp->media->monologue, NULL); update_init_subscribers(mp->media->monologue, OP_OTHER); diff --git a/daemon/media_socket.c b/daemon/media_socket.c index 86137bc33..d605b0535 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1423,8 +1423,11 @@ static const char *kernelize_one(struct rtpengine_target_info *reti, GQueue *out bool non_forwarding = false; bool blackhole = false; - if (sink_handler) + if (sink_handler) { + if (MEDIA_ISSET(sink->media, BLOCK_EGRESS)) + return NULL; sink_handler->kernel_output_idx = -1; + } if (MEDIA_ISSET(media, BLACKHOLE)) blackhole = true; diff --git a/docs/ng_control_protocol.md b/docs/ng_control_protocol.md index d32954a48..5b395607d 100644 --- a/docs/ng_control_protocol.md +++ b/docs/ng_control_protocol.md @@ -840,6 +840,12 @@ Spaces in each string may be replaced by hyphens. (or other DTMF security mechanism) for the relevant call party, identical to using a `block DTMF` message for the call party immediately after. +* `block egress` + + Instructs *rtpengine* to suppress and block other egress media to a remote + client while media playback towards that client is ongoing. Useful for + `play media` messages. + * `block short` or `block short packets` Enables blocking of short RTP packets for the applicable call participant. diff --git a/include/call.h b/include/call.h index 672af007c..63ae58ced 100644 --- a/include/call.h +++ b/include/call.h @@ -189,6 +189,7 @@ enum { #define MEDIA_FLAG_LEGACY_OSRTP SHARED_FLAG_LEGACY_OSRTP #define MEDIA_FLAG_LEGACY_OSRTP_REV SHARED_FLAG_LEGACY_OSRTP_REV #define MEDIA_FLAG_TRANSCODING 0x100000000LL +#define MEDIA_FLAG_BLOCK_EGRESS 0x200000000LL /* struct call_monologue */ #define ML_FLAG_REC_FORWARDING 0x00010000 diff --git a/include/call_interfaces.h b/include/call_interfaces.h index d84ef4dd3..3d3d082f9 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -184,6 +184,7 @@ struct sdp_ng_flags { inject_dtmf:1, detect_dtmf:1, block_dtmf:1, + block_egress:1, t38_decode:1, t38_force:1, t38_stop:1, diff --git a/include/media_player.h b/include/media_player.h index 99ab31ae8..99004b849 100644 --- a/include/media_player.h +++ b/include/media_player.h @@ -20,6 +20,7 @@ struct media_player; typedef struct { long long start_pos; int repeat; + unsigned int block_egress:1; } media_player_opts_t; diff --git a/utils/rtpengine-ng-client b/utils/rtpengine-ng-client index 2f07e108b..368d7cf67 100755 --- a/utils/rtpengine-ng-client +++ b/utils/rtpengine-ng-client @@ -52,6 +52,7 @@ my @flags = qw( early-media block-short recording-vsc + block-egress ); my @string_opts = qw(