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 c881293fdb
commit e4e3112498

@ -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 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. 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 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. the media file could be determined. The duration is given as in integer representing milliseconds.

@ -2050,6 +2050,7 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) {
GQueue monologues; GQueue monologues;
const char *err = NULL; const char *err = NULL;
long long db_id; long long db_id;
long long repeat_times = 1;
err = play_media_select_party(&call, &monologues, input); err = play_media_select_party(&call, &monologues, input);
if (err) if (err)
@ -2060,21 +2061,21 @@ const char *call_play_media_ng(bencode_item_t *input, bencode_item_t *output) {
if (!monologue->player) if (!monologue->player)
monologue->player = media_player_new(monologue); monologue->player = media_player_new(monologue);
repeat_times = bencode_dictionary_get_int_str(input, "repeat-times", 1);
err = "No media file specified"; err = "No media file specified";
if (bencode_dictionary_get_str(input, "file", &str)) { if (bencode_dictionary_get_str(input, "file", &str)) {
err = "Failed to start media playback from file"; 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; goto out;
} }
else if (bencode_dictionary_get_str(input, "blob", &str)) { else if (bencode_dictionary_get_str(input, "blob", &str)) {
err = "Failed to start media playback from blob"; 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; goto out;
} }
else if ((db_id = bencode_dictionary_get_int_str(input, "db-id", 0)) > 0) { else if ((db_id = bencode_dictionary_get_int_str(input, "db-id", 0)) > 0) {
err = "Failed to start media playback from database"; 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; goto out;
} }
else else

@ -115,6 +115,7 @@ struct media_player *media_player_new(struct call_monologue *ml) {
mp->tt_obj.tt = &media_player_thread; mp->tt_obj.tt = &media_player_thread;
mutex_init(&mp->lock); mutex_init(&mp->lock);
mp->run_func = media_player_read_packet; // default mp->run_func = media_player_read_packet; // default
mp->call = obj_get(ml->call); mp->call = obj_get(ml->call);
mp->ml = ml; 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); int ret = av_read_frame(mp->fmtctx, &mp->pkt);
if (ret < 0) { if (ret < 0) {
if (ret == AVERROR_EOF) { 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; return;
} }
ilog(LOG_ERR, "Error while reading from media stream");
return;
} }
if (!mp->fmtctx->streams) { if (!mp->fmtctx->streams) {
@ -471,20 +489,22 @@ found:
// call->master_lock held in W // 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. // needed to have usable duration for some formats. ignore errors.
avformat_find_stream_info(mp->fmtctx, NULL); avformat_find_stream_info(mp->fmtctx, NULL);
mp->next_run = rtpe_now; mp->next_run = rtpe_now;
// give ourselves a bit of a head start with decoding // give ourselves a bit of a head start with decoding
timeval_add_usec(&mp->next_run, -50000); timeval_add_usec(&mp->next_run, -50000);
media_player_read_packet(mp); media_player_read_packet(mp);
mp->repeat = repeat;
} }
#endif #endif
// call->master_lock held in W // 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 #ifdef WITH_TRANSCODING
if (media_player_play_init(mp)) if (media_player_play_init(mp))
return -1; return -1;
@ -498,7 +518,8 @@ int media_player_play_file(struct media_player *mp, const str *file) {
return -1; return -1;
} }
media_player_play_start(mp); media_player_play_start(mp,repeat);
return 0; return 0;
#else #else
@ -555,7 +576,7 @@ static int64_t __mp_avio_seek(void *opaque, int64_t offset, int whence) {
// call->master_lock held in W // 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 #ifdef WITH_TRANSCODING
const char *err; const char *err;
int av_ret = 0; int av_ret = 0;
@ -593,7 +614,7 @@ int media_player_play_blob(struct media_player *mp, const str *blob) {
if (av_ret < 0) if (av_ret < 0)
goto err; goto err;
media_player_play_start(mp); media_player_play_start(mp,repeat);
return 0; return 0;
@ -630,7 +651,7 @@ err:
// call->master_lock held in W // 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; const char *err;
AUTO_CLEANUP_GBUF(query); AUTO_CLEANUP_GBUF(query);
@ -677,7 +698,7 @@ success:;
str blob; str blob;
str_init_len(&blob, row[0], lengths[0]); 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); mysql_free_result(res);
@ -730,7 +751,6 @@ void media_player_free(void) {
#ifdef WITH_TRANSCODING #ifdef WITH_TRANSCODING
void media_player_loop(void *p) { void media_player_loop(void *p) {
//ilog(LOG_DEBUG, "media_player_loop");
timerthread_run(&media_player_thread); timerthread_run(&media_player_thread);
} }
#endif #endif

@ -39,6 +39,7 @@ struct media_player {
const struct streamhandler *crypt_handler; const struct streamhandler *crypt_handler;
struct timeval next_run; struct timeval next_run;
unsigned long repeat;
AVFormatContext *fmtctx; AVFormatContext *fmtctx;
unsigned long duration; // in milliseconds unsigned long duration; // in milliseconds
@ -85,9 +86,9 @@ struct send_timer {
struct media_player *media_player_new(struct call_monologue *); struct media_player *media_player_new(struct call_monologue *);
int media_player_play_file(struct media_player *, const str *); int media_player_play_file(struct media_player *, const str *, long long);
int media_player_play_blob(struct media_player *, const str *); int media_player_play_blob(struct media_player *, const str *, long long);
int media_player_play_db(struct media_player *, long long); int media_player_play_db(struct media_player *, long long, long long);
void media_player_stop(struct media_player *); void media_player_stop(struct media_player *);
int media_player_setup(struct media_player *mp, const struct rtp_payload_type *src_pt); int media_player_setup(struct media_player *mp, const struct rtp_payload_type *src_pt);

Loading…
Cancel
Save