Browse Source

TT#14008 support repeat-times in media player

closes #1159

Change-Id: Idf177b3e9d674d220b9c73a46ecd58453c6e3b39
pull/1163/head
dvillaume 5 years ago
committed by Richard Fuchs
parent
commit
e4e3112498
4 changed files with 44 additions and 18 deletions
  1. +4
    -0
      README.md
  2. +5
    -4
      daemon/call_interfaces.c
  3. +31
    -11
      daemon/media_player.c
  4. +4
    -3
      include/media_player.h

+ 4
- 0
README.md View File

@ -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.


+ 5
- 4
daemon/call_interfaces.c View File

@ -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


+ 31
- 11
daemon/media_player.c View File

@ -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


+ 4
- 3
include/media_player.h View File

@ -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);


Loading…
Cancel
Save