From e4e3112498a4116cddba09b0a6ff5b1963351ef1 Mon Sep 17 00:00:00 2001 From: dvillaume Date: Mon, 11 Jan 2021 10:59:02 -0500 Subject: [PATCH] TT#14008 support repeat-times in media player closes #1159 Change-Id: Idf177b3e9d674d220b9c73a46ecd58453c6e3b39 --- README.md | 4 ++++ daemon/call_interfaces.c | 9 +++++---- daemon/media_player.c | 42 +++++++++++++++++++++++++++++----------- include/media_player.h | 7 ++++--- 4 files changed, 44 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 4632e06e7..028d443a8 100644 --- a/README.md +++ b/README.md @@ -1795,6 +1795,10 @@ Media files can be provided through one of these keys: database via (at the minimum) the `mysql-host` and `mysql-query` config keys. The daemon will then retrieve the media file as a binary blob (not a file name!) from the database via the provided query. +* `repeat-times` + + Contains an integer. How many times to repeat playback of the media. Default is 1. + In addition to the `result` key, the response dictionary may contain the key `duration` if the length of the media file could be determined. The duration is given as in integer representing milliseconds. diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index 0fdcece04..445eecf2b 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -2050,6 +2050,7 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) { GQueue monologues; const char *err = NULL; long long db_id; + long long repeat_times = 1; err = play_media_select_party(&call, &monologues, input); if (err) @@ -2060,21 +2061,21 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) { if (!monologue->player) monologue->player = media_player_new(monologue); - + repeat_times = bencode_dictionary_get_int_str(input, "repeat-times", 1); err = "No media file specified"; if (bencode_dictionary_get_str(input, "file", &str)) { err = "Failed to start media playback from file"; - if (media_player_play_file(monologue->player, &str)) + if (media_player_play_file(monologue->player, &str,repeat_times)) goto out; } else if (bencode_dictionary_get_str(input, "blob", &str)) { err = "Failed to start media playback from blob"; - if (media_player_play_blob(monologue->player, &str)) + if (media_player_play_blob(monologue->player, &str,repeat_times)) goto out; } else if ((db_id = bencode_dictionary_get_int_str(input, "db-id", 0)) > 0) { err = "Failed to start media playback from database"; - if (media_player_play_db(monologue->player, db_id)) + if (media_player_play_db(monologue->player, db_id,repeat_times)) goto out; } else diff --git a/daemon/media_player.c b/daemon/media_player.c index 685ea3dfa..9447f0051 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -115,6 +115,7 @@ struct media_player *media_player_new(struct call_monologue *ml) { mp->tt_obj.tt = &media_player_thread; mutex_init(&mp->lock); + mp->run_func = media_player_read_packet; // default mp->call = obj_get(ml->call); mp->ml = ml; @@ -386,11 +387,28 @@ static void media_player_read_packet(struct media_player *mp) { int ret = av_read_frame(mp->fmtctx, &mp->pkt); if (ret < 0) { if (ret == AVERROR_EOF) { - ilog(LOG_DEBUG, "EOF reading from media stream"); + if (mp->repeat > 1){ + ilog(LOG_DEBUG, "EOF reading from media stream but will repeat %li time",mp->repeat); + mp->repeat = mp->repeat - 1; + int64_t ret64 = avio_seek(mp->fmtctx->pb, 0, SEEK_SET); + if (ret64 != 0) + ilog(LOG_ERR, "Failed to seek to beginning of media file"); + ret = av_seek_frame(mp->fmtctx, -1, 0, 0); + if (ret < 0) + ilog(LOG_ERR, "Failed to seek to beginning of media file"); + ret = av_read_frame(mp->fmtctx, &mp->pkt); + } else { + ilog(LOG_DEBUG, "EOF reading from media stream"); + return; + + } + + } + if (ret < 0 && ret != AVERROR_EOF) { + ilog(LOG_ERR, "Error while reading from media stream"); return; } - ilog(LOG_ERR, "Error while reading from media stream"); - return; + } if (!mp->fmtctx->streams) { @@ -471,20 +489,22 @@ found: // call->master_lock held in W -static void media_player_play_start(struct media_player *mp) { +static void media_player_play_start(struct media_player *mp, long long repeat) { // needed to have usable duration for some formats. ignore errors. avformat_find_stream_info(mp->fmtctx, NULL); mp->next_run = rtpe_now; // give ourselves a bit of a head start with decoding timeval_add_usec(&mp->next_run, -50000); + media_player_read_packet(mp); + mp->repeat = repeat; } #endif // call->master_lock held in W -int media_player_play_file(struct media_player *mp, const str *file) { +int media_player_play_file(struct media_player *mp, const str *file, long long repeat) { #ifdef WITH_TRANSCODING if (media_player_play_init(mp)) return -1; @@ -498,7 +518,8 @@ int media_player_play_file(struct media_player *mp, const str *file) { return -1; } - media_player_play_start(mp); + media_player_play_start(mp,repeat); + return 0; #else @@ -555,7 +576,7 @@ static int64_t __mp_avio_seek(void *opaque, int64_t offset, int whence) { // call->master_lock held in W -int media_player_play_blob(struct media_player *mp, const str *blob) { +int media_player_play_blob(struct media_player *mp, const str *blob, long long repeat) { #ifdef WITH_TRANSCODING const char *err; int av_ret = 0; @@ -593,7 +614,7 @@ int media_player_play_blob(struct media_player *mp, const str *blob) { if (av_ret < 0) goto err; - media_player_play_start(mp); + media_player_play_start(mp,repeat); return 0; @@ -630,7 +651,7 @@ err: // call->master_lock held in W -int media_player_play_db(struct media_player *mp, long long id) { +int media_player_play_db(struct media_player *mp, long long id, long long repeat) { const char *err; AUTO_CLEANUP_GBUF(query); @@ -677,7 +698,7 @@ success:; str blob; str_init_len(&blob, row[0], lengths[0]); - int ret = media_player_play_blob(mp, &blob); + int ret = media_player_play_blob(mp, &blob, repeat); mysql_free_result(res); @@ -730,7 +751,6 @@ void media_player_free(void) { #ifdef WITH_TRANSCODING void media_player_loop(void *p) { - //ilog(LOG_DEBUG, "media_player_loop"); timerthread_run(&media_player_thread); } #endif diff --git a/include/media_player.h b/include/media_player.h index 3f9da1a95..bf8f5693a 100644 --- a/include/media_player.h +++ b/include/media_player.h @@ -39,6 +39,7 @@ struct media_player { const struct streamhandler *crypt_handler; struct timeval next_run; + unsigned long repeat; AVFormatContext *fmtctx; unsigned long duration; // in milliseconds @@ -85,9 +86,9 @@ struct send_timer { struct media_player *media_player_new(struct call_monologue *); -int media_player_play_file(struct media_player *, const str *); -int media_player_play_blob(struct media_player *, const str *); -int media_player_play_db(struct media_player *, long long); +int media_player_play_file(struct media_player *, const str *, long long); +int media_player_play_blob(struct media_player *, const str *, long long); +int media_player_play_db(struct media_player *, long long, long long); void media_player_stop(struct media_player *); int media_player_setup(struct media_player *mp, const struct rtp_payload_type *src_pt);