Browse Source

MT#61630 Generalize `moh-max-duration`, add `repeat-duration`

Make `moh-max-duration` available for both
music-on-hold functionality as well as
for the media player.

For that to work, do the following:
- keep `moh-max-duration` config option only for MoH,
  if not set (so 0) by default is 1800000ms (half an hour)
- for the play media functionality introduce flag option
  `repeat-duration`, by default is disabled

Policy changes:
- duration counter can be used in common with repeats
  counter, but then takes a precedence over it.
  Hence if first a duration is underflown, then EOF triggered.
  Otherwise if the duration counter is still positive, but
  repeats are negative, then do EOF based on repeats.
- the repeats counter will always count down during each
  iteration, even when used together with the duration counter
  For MoH to survive, the repeats counter is simple set to 999
  to let the duration counter always win over repeats one
- MoH cannot take duration disabled, since otherwise
  would make no sense for it. Hence always takes internally
  defined value 1800000ms (half an hour) if not defined
  by the configuration option

Backwards compatibility:
- is kept in regards of repeats counter
- is kept in regards of the play media functionality

Change-Id: I48ff3c17c9bed31f80c3106b275b703a9ccb4b26
pull/1897/head
Donat Zenichev 11 months ago
parent
commit
67bfa5a5df
8 changed files with 55 additions and 20 deletions
  1. +1
    -0
      daemon/call.c
  2. +5
    -0
      daemon/call_interfaces.c
  3. +6
    -2
      daemon/main.c
  4. +29
    -16
      daemon/media_player.c
  5. +11
    -0
      docs/ng_control_protocol.md
  6. +2
    -1
      etc/rtpengine.conf
  7. +1
    -0
      include/call_interfaces.h
  8. +0
    -1
      include/media_player.h

+ 1
- 0
daemon/call.c View File

@ -2765,6 +2765,7 @@ static void __call_monologue_init_from_flags(struct call_monologue *ml, struct c
media_player_new(&ml->rec_player, ml);
media_player_opts_t opts = MPO(
.repeat = flags->repeat_times,
.duration_spent = flags->repeat_duration,
.start_pos = flags->start_pos,
.block_egress = !!flags->block_egress,
.codec_set = flags->codec_set,


+ 5
- 0
daemon/call_interfaces.c View File

@ -1351,6 +1351,7 @@ void call_ng_flags_init(sdp_ng_flags *out, enum ng_opmode opmode) {
out->delete_delay = -1;
out->volume = 9999;
out->digit = -1;
out->repeat_duration = -1;
out->frequencies = g_array_new(false, false, sizeof(int));
for (int i = 0; i < __MT_MAX; ++i)
out->sdp_media_remove[i] = false;
@ -1929,6 +1930,9 @@ void call_ng_main_flags(const ng_parser_t *parser, str *key, parser_arg value, h
case CSH_LOOKUP("repeat-times"):
out->repeat_times = parser->get_int_str(value, out->repeat_times);
break;
case CSH_LOOKUP("repeat-duration"):
out->repeat_duration = parser->get_int_str(value, out->repeat_duration);
break;
case CSH_LOOKUP("replace"):
call_ng_flags_str_list(parser, value, call_ng_flags_replace, out);
break;
@ -3634,6 +3638,7 @@ const char *call_play_media_ng(ng_command_ctx_t *ctx) {
media_player_opts_t opts = MPO(
.repeat = flags.repeat_times,
.duration_spent = flags.repeat_duration,
.start_pos = flags.start_pos,
.block_egress = !!flags.block_egress,
.codec_set = flags.codec_set,


+ 6
- 2
daemon/main.c View File

@ -112,7 +112,7 @@ struct rtpengine_config rtpe_config = {
.mqtt_publish_interval = 5000,
.dtmf_digit_delay = 2500,
.rtcp_interval = 5000,
.moh_max_duration = 1800000, // in ms
.moh_max_duration = -1, // disabled by default
.common = {
.log_levels = {
[log_level_index_internals] = -1,
@ -697,7 +697,7 @@ static void options(int *argc, char ***argv, GHashTable *templates) {
#endif
{ "janus-secret", 0,0, G_OPTION_ARG_STRING, &rtpe_config.janus_secret,"Admin secret for Janus protocol","STRING"},
{ "rtcp-interval", 0,0, G_OPTION_ARG_INT, &rtpe_config.rtcp_interval,"Delay in milliseconds between RTCP packets when generate-rtcp flag is on, where random dispersion < 1 sec is added on top","INT"},
{ "moh-max-duration", 0,0, G_OPTION_ARG_INT, &rtpe_config.moh_max_duration, "Music-on-hold max possible duration (in milliseconds). If set to 0 then will be ignored.", "INT"},
{ "moh-max-duration", 0,0, G_OPTION_ARG_INT, &rtpe_config.moh_max_duration, "Max possible duration (in milliseconds) that can be spent on playing a file. If set to 0 then will be ignored.", "INT"},
{ "max-recv-iters", 0, 0, G_OPTION_ARG_INT, &rtpe_config.max_recv_iters, "Maximum continuous reading cycles in UDP poller loop.", "INT"},
{ "vsc-start-rec",0,0, G_OPTION_ARG_STRING, &rtpe_config.vsc_start_rec.s,"DTMF VSC to start recording.", "STRING"},
{ "vsc-stop-rec",0,0, G_OPTION_ARG_STRING, &rtpe_config.vsc_stop_rec.s,"DTMF VSC to stop recording.", "STRING"},
@ -867,6 +867,10 @@ static void options(int *argc, char ***argv, GHashTable *templates) {
if (rtpe_config.max_recv_iters < 1)
die("Invalid max-recv-iters value");
/* if not set, define by default to half an hour */
if (rtpe_config.moh_max_duration <= 0)
rtpe_config.moh_max_duration = 1800000;
if (rtpe_config.timeout <= 0)
rtpe_config.timeout = 60;


+ 29
- 16
daemon/media_player.c View File

@ -1013,27 +1013,39 @@ static bool media_player_read_packet(struct media_player *mp) {
int ret = av_read_frame(mp->coder.fmtctx, mp->coder.pkt);
if (ret < 0) {
if (ret == AVERROR_EOF) {
/* for moh: count based on duration */
if (mp->moh && mp->opts.duration_spent > 0) {
ilog(LOG_DEBUG, "EOF reading from media stream but will be played further for duration of '%lld' ms",
mp->opts.duration_spent);
/* moh counter for the max spent duration (in milliseconds) */
mp->opts.duration_spent = mp->opts.duration_spent - mp->coder.duration;
ret = media_player_find_file_begin(mp);
/* for play media: count based on repeats */
} else if (!mp->moh && mp->opts.repeat > 1) {
ilog(LOG_DEBUG, "EOF reading from media stream but will repeat '%i' time",
mp->opts.repeat);
mp->opts.repeat = mp->opts.repeat - 1;
ret = media_player_find_file_begin(mp);
} else {
/* Duration counter cannot underflow and is always aligned to 0 when used.
* By default is -1.
* If either a duration or repeats counter are done, then the reading process
* is considered EOF.
*/
if (mp->opts.duration_spent == 0 ||
mp->opts.repeat <= 1)
{
ilog(LOG_DEBUG, "EOF reading from media stream");
return true;
}
ret = media_player_find_file_begin(mp);
/* counter for the max spent duration (in milliseconds)
* duration takes precedence over repeats, if used together
*/
if (mp->opts.duration_spent > 0) {
ilog(LOG_DEBUG, "EOF reading from stream but will be played further due to available duration '%lld'",
mp->opts.duration_spent);
mp->opts.duration_spent = mp->opts.duration_spent - mp->coder.duration;
/* don't let the duration counter to underflow */
if (mp->opts.duration_spent < 0)
mp->opts.duration_spent = 0;
}
/* counter for the max repeats
* still count down each time, even if we are based on max duration in milliseconds */
if (mp->opts.repeat > 1) {
ilog(LOG_DEBUG, "EOF reading from stream but will be played further due to available repeats '%d'",
mp->opts.repeat);
mp->opts.repeat--;
}
}
if (ret < 0 && ret != AVERROR_EOF) {
ilog(LOG_ERR, "Error while reading from media stream");
@ -1282,6 +1294,7 @@ const char * call_check_moh(struct call_monologue *from_ml, struct call_monologu
const char *errstr = NULL;
media_player_opts_t opts = MPO(
.repeat = 999,
/* MoH always has duration set (even if not defined) */
.duration_spent = rtpe_config.moh_max_duration,
.start_pos = 0,
.block_egress = 1,


+ 11
- 0
docs/ng_control_protocol.md View File

@ -2095,6 +2095,17 @@ Media files can be provided through one of these keys:
Contains an integer. How many times to repeat playback of the media. Default is 1.
* `repeat-duration`
Contains an integer. How much time in milliseconds is a playback of the media to be minimally iterated.
E.g. if set to 10000ms and the playback's length is 1000ms, then this playback will be iterated
10 times due to limitation set to 10000ms.
If used together with `repeat-times` then the following logic takes place:
if `repeat-duration` hits the trigger earlier, then this playback will be stopped,
otherwise if the `repeat-duration` is still positive, but the `repeat-times` counter went down to 1,
then still the playback is to be stopped.
By default is disabled.
* `start-pos`
Contains an integer. The start frame position to begin the playback from.


+ 2
- 1
etc/rtpengine.conf View File

@ -152,7 +152,8 @@ recording-method = proc
# socket-cpu-affinity = -1
# rtcp-interval = 5000
# music-on-hold max possible duration (in ms), if set 0 then will be ignored
# music-on-hold max possible duration (in ms).
# When not defined (set to 0), it takes 1800000ms default value.
# moh-max-duration = 1800000
# signalling templates (see key `templates` above)


+ 1
- 0
include/call_interfaces.h View File

@ -133,6 +133,7 @@ struct sdp_ng_flags {
int media_rec_slot_answer;
int media_rec_slots;
int repeat_times;
long long repeat_duration;
int delete_delay;
str file;
str moh_file;


+ 0
- 1
include/media_player.h View File

@ -34,7 +34,6 @@ typedef struct {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
struct media_player_cache_entry;
struct media_player_content_index {


Loading…
Cancel
Save