video: add an option to tune waiting for video timing

Probably mostly useful for the libmpv render API.
This commit is contained in:
wm4 2018-03-13 11:23:23 +01:00 committed by Kevin Mitchell
parent 9ca1a1b068
commit 2c572e2bb1
6 changed files with 50 additions and 2 deletions

View File

@ -5410,6 +5410,26 @@ Miscellaneous
out. This delay in reaction time to sudden A/V offsets should be the only
side effect of turning this option on, for all sound drivers.
``--video-timing-offset=<seconds>``
Control how long before video display target time the frame should be
rendered (default: 0.050). If a video frame should be displayed at a
certain time, the VO will start rendering the frame earlier, and then will
perform a blocking wait until the display time, and only then "swap" the
frame to display. The rendering cannot start before the previous frame is
displayed, so this value is implicitly limited by the video framerate. With
normal video frame rates, the default value will ensure that rendering is
always immediately started after the previous frame was displayed. On the
other hand, setting a too high value can reduce responsiveness with low
FPS value.
For client API users using the render API (or the deprecated ``opengl-cb``
API), this option is interesting, because you can stop the render API
from limiting your FPS (see ``mpv_render_context_render()`` documentation).
This applies only to audio timing modes (e.g. ``--video-sync=audio``). In
other modes (``--video-sync=display-...``), video timing relies on vsync
blocking, and this option is not used.
``--video-sync=<audio|...>``
How the player synchronizes audio and video.

View File

@ -270,6 +270,12 @@ void mpv_render_context_set_update_callback(mpv_render_context *ctx,
* notifies you when a new frame was added. The details potentially depend on
* the backends and the provided parameters.
*
* Generally, libmpv will invoke your update callback some time before the video
* frame should be shown, and then lets this function block until the supposed
* display time. This will limit your rendering to video FPS. You can prevent
* this by setting the "video-timing-offset" global option to 0. (This applies
* only to "audio" video sync mode.)
*
* @param ctx a valid render context
* @param params an array of parameters, terminated by type==0. Which parameters
* are required depends on the backend. It's left unspecified what

View File

@ -616,6 +616,9 @@ extern const char m_option_path_separator;
#define OPT_FLOATRANGE(...) \
OPT_RANGE_(float, __VA_ARGS__, .type = &m_option_type_float)
#define OPT_DOUBLERANGE(...) \
OPT_RANGE_(double, __VA_ARGS__, .type = &m_option_type_double)
#define OPT_INTPAIR(...) \
OPT_GENERAL_NOTYPE(__VA_ARGS__, .type = &m_option_type_intpair)

View File

@ -139,6 +139,7 @@ static const m_option_t mp_vo_opt_list[] = {
OPT_FLAG("keepaspect-window", keepaspect_window, 0),
OPT_FLAG("hidpi-window-scale", hidpi_window_scale, 0),
OPT_FLAG("native-fs", native_fs, 0),
OPT_DOUBLERANGE("video-timing-offset", timing_offset, 0, 0.0, 1.0),
#if HAVE_X11
OPT_CHOICE("x11-netwm", x11_netwm, 0,
({"auto", 0}, {"no", -1}, {"yes", 1})),
@ -176,6 +177,7 @@ const struct m_sub_options vo_sub_opts = {
.x11_bypass_compositor = 2,
.mmcss_profile = "Playback",
.ontop_level = -1,
.timing_offset = 0.050,
},
};

View File

@ -50,6 +50,8 @@ typedef struct mp_vo_opts {
char *mmcss_profile;
double timing_offset;
// vo_drm
struct sws_opts *sws_opts;
// vo_drm

View File

@ -147,6 +147,7 @@ struct vo_internal {
int64_t num_successive_vsyncs;
int64_t flip_queue_offset; // queue flip events at most this much in advance
int64_t timing_offset; // same (but from options; not VO configured)
int64_t delayed_count;
int64_t drop_count;
@ -212,11 +213,23 @@ static void dispatch_wakeup_cb(void *ptr)
vo_wakeup(vo);
}
// Initialize or update options from vo->opts
static void read_opts(struct vo *vo)
{
struct vo_internal *in = vo->in;
pthread_mutex_lock(&in->lock);
in->timing_offset = (uint64_t)(vo->opts->timing_offset * 1e6);
pthread_mutex_unlock(&in->lock);
}
static void update_opts(void *p)
{
struct vo *vo = p;
if (m_config_cache_update(vo->opts_cache)) {
read_opts(vo);
// "Legacy" update of video position related options.
if (vo->driver->control)
vo->driver->control(vo, VOCTRL_SET_PANSCAN, NULL);
@ -728,8 +741,9 @@ bool vo_is_ready_for_frame(struct vo *vo, int64_t next_pts)
if (r && next_pts >= 0) {
// Don't show the frame too early - it would basically freeze the
// display by disallowing OSD redrawing or VO interaction.
// Actually render the frame at earliest 50ms before target time.
next_pts -= (uint64_t)(0.050 * 1e6);
// Actually render the frame at earliest the given offset before target
// time.
next_pts -= in->timing_offset;
next_pts -= in->flip_queue_offset;
int64_t now = mp_time_us();
if (next_pts > now)
@ -1003,6 +1017,7 @@ static void *vo_thread(void *ptr)
if (r < 0)
return NULL;
read_opts(vo);
update_display_fps(vo);
vo_event(vo, VO_EVENT_WIN_STATE);