diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 21a984e480..f230c636b9 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -216,6 +216,21 @@ Playback Control speed higher than normal automatically inserts the ``scaletempo2`` audio filter. +``--rt-catchup`` + Enable the player to speed up by a factor equal to the sum of 1, and the + square of the product of how many seconds behind the the delay given by + ``--rt-catchup-max-delay`` the player has fallen and the value given by + ``--rt-catchup-multiplier`` unless the delay does not exceed the delay + given by ``--rt-catchup-max-delay``. + +``--rt-catchup-max-delay=<0.0..>`` + The maximum delay in seconds behind the media source the player may reach + before it starts speeding up, if ``--rt-catchup`` is enabled. + +``--rt-catchup-multiplier=<0.0..>`` + A coefficient applied during the speed multiplier calculation according to + ``--rt-catchup`` and ``--rt-catchup-max-delay`` + ``--pause`` Start the player in paused state. diff --git a/options/options.c b/options/options.c index 6d38af53b4..07c6883864 100644 --- a/options/options.c +++ b/options/options.c @@ -568,6 +568,13 @@ static const m_option_t mp_opts[] = { // set a-v distance {"audio-delay", OPT_FLOAT(audio_delay)}, + // set live/realtime catch-up parameters + {"rt-catchup", OPT_FLAG(realtime_catchup)}, + {"rt-catchup-multiplier", OPT_DOUBLE(realtime_catchup_speed_multiplier), + M_RANGE(0, DBL_MAX)}, + {"rt-catchup-max-delay", OPT_DOUBLE(realtime_catchup_max_delay), + M_RANGE(0, DBL_MAX)}, + // ------------------------- codec/vfilter options -------------------- {"af-defaults", OPT_SETTINGSLIST(af_defs, &af_obj_list), diff --git a/options/options.h b/options/options.h index 4eb5ef07c7..c0f94ec951 100644 --- a/options/options.h +++ b/options/options.h @@ -224,6 +224,9 @@ typedef struct MPOpts { int hr_seek_framedrop; float audio_delay; float default_max_pts_correction; + int realtime_catchup; + double realtime_catchup_speed_multiplier; + double realtime_catchup_max_delay; int autosync; int frame_dropping; int video_latency_hacks; diff --git a/player/audio.c b/player/audio.c index 06ea1262a6..d0f43801b1 100644 --- a/player/audio.c +++ b/player/audio.c @@ -174,9 +174,29 @@ void audio_update_volume(struct MPContext *mpctx) ao_set_gain(ao_c->ao, gain); } +// Calculate a speed multiplier proportional to the delay between the current +// playback time and the media source. This multiplier is used to keep up with a +// real-time source such as a live stream. +static double calc_realtime_catchup_speed(struct MPContext *mpctx) +{ + double max_delay = mpctx->opts->realtime_catchup_max_delay; + double delay = get_time_length(mpctx) - get_playback_time(mpctx); + + if (delay > max_delay) { + double multiplier = mpctx->opts->realtime_catchup_speed_multiplier; + return 1.0 + powf((delay - max_delay) * multiplier, 2.0); + } else { + return 1.0; + } +} + // Call this if opts->playback_speed or mpctx->speed_factor_* change. void update_playback_speed(struct MPContext *mpctx) { + if (mpctx->opts->realtime_catchup) { + mpctx->opts->playback_speed = calc_realtime_catchup_speed(mpctx); + } + mpctx->audio_speed = mpctx->opts->playback_speed * mpctx->speed_factor_a; mpctx->video_speed = mpctx->opts->playback_speed * mpctx->speed_factor_v;