From bab3c94fd08405745545d6cb02693063f2e5607d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Ned=C5=BEibovi=C4=87?= Date: Mon, 7 Nov 2022 16:03:38 +0100 Subject: [PATCH] Implement playing from a start position. --- README.md | 7 ++++++- daemon/call_interfaces.c | 9 +++++++-- daemon/media_player.c | 19 ++++++++++++++----- include/call_interfaces.h | 1 + include/media_player.h | 5 +++-- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1ff515dbe..0f2af5ec2 100644 --- a/README.md +++ b/README.md @@ -2093,6 +2093,10 @@ 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. +* `start-pos` + + Contains an integer. The start frame position to begin the playback from. + 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. @@ -2101,7 +2105,8 @@ the media file could be determined. The duration is given as in integer represen Stops the playback previously started by a `play media` message. Media playback stops automatically when the end of the media file is reached, so this message is only useful for prematurely stopping playback. -The same participant selection keys as for the `play media` message can and must be used. +The same participant selection keys as for the `play media` message can and must be used. Will return the +last frame played in `last-frame-pos` key. `play DTMF` Message ------------------- diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index d2957aa17..e9e43ee04 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -1458,6 +1458,9 @@ static void call_ng_main_flags(struct sdp_ng_flags *out, str *key, bencode_item_ case CSH_LOOKUP("file"): out->file = s; break; + case CSH_LOOKUP("start-pos"): + out->start_pos = bencode_get_integer_str(value, out->start_pos); + break; case CSH_LOOKUP("blob"): out->blob = s; break; @@ -2839,7 +2842,7 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) { if (flags.repeat_times <= 0) flags.repeat_times = 1; if (flags.file.len) { - if (media_player_play_file(monologue->player, &flags.file, flags.repeat_times)) + if (media_player_play_file(monologue->player, &flags.file, flags.repeat_times, flags.start_pos)) return "Failed to start media playback from file"; } else if (flags.blob.len) { @@ -2869,6 +2872,7 @@ const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) { AUTO_CLEANUP_NULL(struct call *call, call_unlock_release); AUTO_CLEANUP(GQueue monologues, g_queue_clear); const char *err = NULL; + long long last_frame_pos = 0; err = play_media_select_party(&call, &monologues, input, NULL); if (err) @@ -2880,8 +2884,9 @@ const char *call_stop_media_ng(bencode_item_t *input, bencode_item_t *output) { if (!monologue->player) return "Not currently playing media"; - media_player_stop(monologue->player); + last_frame_pos = media_player_stop(monologue->player); } + bencode_dictionary_add_integer(output, "last-frame-pos", last_frame_pos); return NULL; #else diff --git a/daemon/media_player.c b/daemon/media_player.c index d103ac3e2..07c313043 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -84,9 +84,12 @@ static void media_player_shutdown(struct media_player *mp) { #endif -void media_player_stop(struct media_player *mp) { +long long media_player_stop(struct media_player *mp) { #ifdef WITH_TRANSCODING media_player_shutdown(mp); + if (!mp) + return 0; + return mp->last_frame_ts; #endif } @@ -442,6 +445,7 @@ static void media_player_read_packet(struct media_player *mp) { goto out; } + mp->last_frame_ts = mp->pkt->pts; AVStream *avs = mp->fmtctx->streams[0]; if (!avs) { ilog(LOG_ERR, "No AVStream present in format context"); @@ -515,7 +519,7 @@ found: // call->master_lock held in W -static void media_player_play_start(struct media_player *mp, long long repeat) { +static void media_player_play_start(struct media_player *mp, long long repeat, long long start_pos) { // needed to have usable duration for some formats. ignore errors. avformat_find_stream_info(mp->fmtctx, NULL); @@ -523,6 +527,11 @@ static void media_player_play_start(struct media_player *mp, long long repeat) { // give ourselves a bit of a head start with decoding timeval_add_usec(&mp->next_run, -50000); + // if start_pos is positive, try to seek to that position + if (start_pos > 0) { + ilog(LOG_DEBUG, "Seeking to position %lli", start_pos); + av_seek_frame(mp->fmtctx, 0, start_pos, 0); + } media_player_read_packet(mp); mp->repeat = repeat; } @@ -530,7 +539,7 @@ static void media_player_play_start(struct media_player *mp, long long repeat) { // call->master_lock held in W -int media_player_play_file(struct media_player *mp, const str *file, long long repeat) { +int media_player_play_file(struct media_player *mp, const str *file, long long repeat, long long start_pos) { #ifdef WITH_TRANSCODING if (media_player_play_init(mp)) return -1; @@ -544,7 +553,7 @@ int media_player_play_file(struct media_player *mp, const str *file, long long r return -1; } - media_player_play_start(mp,repeat); + media_player_play_start(mp, repeat, start_pos); return 0; @@ -640,7 +649,7 @@ int media_player_play_blob(struct media_player *mp, const str *blob, long long r if (av_ret < 0) goto err; - media_player_play_start(mp,repeat); + media_player_play_start(mp, repeat, 0); return 0; diff --git a/include/call_interfaces.h b/include/call_interfaces.h index b4edfa5d4..1e896d2b3 100644 --- a/include/call_interfaces.h +++ b/include/call_interfaces.h @@ -102,6 +102,7 @@ struct sdp_ng_flags { long long db_id; long long duration; long long pause; + long long start_pos; unsigned int asymmetric:1, protocol_accept:1, no_redis_update:1, diff --git a/include/media_player.h b/include/media_player.h index 53bdeca73..36634a28f 100644 --- a/include/media_player.h +++ b/include/media_player.h @@ -49,6 +49,7 @@ struct media_player { unsigned long seq; unsigned long sync_ts; struct timeval sync_ts_tv; + long long last_frame_ts; AVIOContext *avioctx; str *blob; @@ -86,10 +87,10 @@ struct send_timer { struct media_player *media_player_new(struct call_monologue *); -int media_player_play_file(struct media_player *, const str *, long long); +int media_player_play_file(struct media_player *, const str *, long long, 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 *); +long long media_player_stop(struct media_player *); int media_player_setup(struct media_player *mp, const struct rtp_payload_type *src_pt); void media_player_set_media(struct media_player *mp, struct call_media *media);