summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-08-17 02:50:59 +0200
committerwm4 <wm4@nowhere>2014-08-17 02:50:59 +0200
commit5b64f5ad35ba00d894c9efb1b12fa93ed1aa27fa (patch)
treedb520914a6aef094aef098d885ee0ff5d0a6a2c7
parent4822056db7a9f717eace337aeda760c35ab114d5 (diff)
downloadmpv-5b64f5ad35ba00d894c9efb1b12fa93ed1aa27fa.tar.bz2
mpv-5b64f5ad35ba00d894c9efb1b12fa93ed1aa27fa.tar.xz
video: take refresh rate changes into account
This works only on X11, and only if the refresh rate changes due to the window being moved to another screen (detected by us). It doesn't include system screen reconfiguration yet. This calls VOCTRL_GET_DISPLAY_FPS on every frame, which makes me uneasy. It means extra thread communication with the win32 and Cocoa backends. On the other hand, a frame doesn't happen _that_ often, and the communication should still be pretty cheap and fast, so it's probably ok. Also needs some extra fuzz for vo_vdpau.c, because that does everything differently.
-rw-r--r--video/out/vo.c37
-rw-r--r--video/out/vo.h1
-rw-r--r--video/out/vo_vdpau.c27
3 files changed, 37 insertions, 28 deletions
diff --git a/video/out/vo.c b/video/out/vo.c
index bb98160883..8adabc70e2 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -126,7 +126,6 @@ struct vo_internal {
int wakeup_pipe[2]; // used for VOs that use a unix FD for waiting
- char *window_title;
bool hasframe;
bool request_redraw;
@@ -135,7 +134,6 @@ struct vo_internal {
int64_t flip_queue_offset; // queue flip events at most this much in advance
int64_t last_flip;
- int64_t vsync_interval;
int64_t drop_count;
bool dropped_frame; // the previous frame was dropped
struct mp_image *dropped_image; // used to possibly redraw the dropped frame
@@ -146,6 +144,10 @@ struct vo_internal {
struct mp_image *frame_queued; // the image that should be rendered
int64_t frame_pts; // realtime of intended display
int64_t frame_duration; // realtime frame duration (for framedrop)
+
+ // --- The following fields can be accessed from the VO thread only
+ int64_t vsync_interval;
+ char *window_title;
};
static void forget_frames(struct vo *vo);
@@ -295,6 +297,21 @@ void vo_destroy(struct vo *vo)
dealloc_vo(vo);
}
+// to be called from VO thread only
+static void update_display_fps(struct vo *vo)
+{
+ double display_fps = 1000.0; // assume infinite if unset
+ if (vo->global->opts->frame_drop_fps > 0) {
+ display_fps = vo->global->opts->frame_drop_fps;
+ } else {
+ vo->driver->control(vo, VOCTRL_GET_DISPLAY_FPS, &display_fps);
+ }
+ int64_t n_interval = MPMAX((int64_t)(1e6 / display_fps), 1);
+ if (vo->in->vsync_interval != n_interval)
+ MP_VERBOSE(vo, "Assuming %f FPS for framedrop.\n", display_fps);
+ vo->in->vsync_interval = n_interval;
+}
+
static void check_vo_caps(struct vo *vo)
{
int rot = vo->params->rotate;
@@ -331,14 +348,7 @@ static void run_reconfig(void *p)
}
forget_frames(vo); // implicitly synchronized
- double display_fps = 1000.0; // assume infinite if unset
- if (vo->global->opts->frame_drop_fps > 0) {
- display_fps = vo->global->opts->frame_drop_fps;
- } else {
- vo->driver->control(vo, VOCTRL_GET_DISPLAY_FPS, &display_fps);
- }
- vo->in->vsync_interval = MPMAX((int64_t)(1e6 / display_fps), 1);
- MP_VERBOSE(vo, "Assuming %f FPS for framedrop.\n", display_fps);
+ update_display_fps(vo);
}
int vo_reconfig(struct vo *vo, struct mp_image_params *params, int flags)
@@ -529,6 +539,8 @@ static bool render_frame(struct vo *vo)
{
struct vo_internal *in = vo->in;
+ update_display_fps(vo);
+
pthread_mutex_lock(&in->lock);
int64_t pts = in->frame_pts;
@@ -770,6 +782,11 @@ void vo_set_flip_queue_offset(struct vo *vo, int64_t us)
pthread_mutex_unlock(&in->lock);
}
+int64_t vo_get_vsync_interval(struct vo *vo)
+{
+ return vo->in->vsync_interval;
+}
+
/**
* \brief lookup an integer in a table, table must have 0 as the last key
* \param key key to search for
diff --git a/video/out/vo.h b/video/out/vo.h
index 9077ab49b1..93094117a6 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -289,6 +289,7 @@ void vo_set_paused(struct vo *vo, bool paused);
int64_t vo_get_drop_count(struct vo *vo);
void vo_set_flip_queue_offset(struct vo *vo, int64_t us);
+int64_t vo_get_vsync_interval(struct vo *vo);
void vo_wakeup(struct vo *vo);
const char *vo_get_window_title(struct vo *vo);
diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c
index 6699e1b906..005e733357 100644
--- a/video/out/vo_vdpau.c
+++ b/video/out/vo_vdpau.c
@@ -329,27 +329,11 @@ static int win_x11_init_vdpau_flip_queue(struct vo *vo)
CHECK_VDP_WARNING(vo, "Error setting colorkey");
}
- vc->vsync_interval = 1;
if (vc->composite_detect && vo_x11_screen_is_composited(vo)) {
MP_INFO(vo, "Compositing window manager detected. Assuming timing info "
"is inaccurate.\n");
- } else if (vc->user_fps > 0) {
- vc->vsync_interval = 1e9 / vc->user_fps;
- MP_INFO(vo, "Assuming user-specified display refresh rate of %.3f Hz.\n",
- vc->user_fps);
- } else if (vc->user_fps == 0) {
- double fps = vo_x11_vm_get_fps(vo);
- if (fps < 1)
- MP_WARN(vo, "Failed to get display FPS\n");
- else {
- vc->vsync_interval = 1e9 / fps;
- // This is verbose, but I'm not yet sure how common wrong values are
- MP_INFO(vo, "Got display refresh rate %.3f Hz.\n", fps);
- MP_INFO(vo, "If that value looks wrong give the "
- "-vo vdpau:fps=X suboption manually.\n");
- }
- } else
- MP_VERBOSE(vo, "framedrop/timing logic disabled by user.\n");
+ vc->user_fps = -1;
+ }
return 0;
}
@@ -737,6 +721,13 @@ static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
if (!check_preemption(vo))
return;
+ vc->vsync_interval = 1;
+ if (vc->user_fps > 0) {
+ vc->vsync_interval = 1e9 / vc->user_fps;
+ } else if (vc->user_fps == 0) {
+ vc->vsync_interval = vo_get_vsync_interval(vo) * 1000;
+ }
+
if (duration > INT_MAX / 1000)
duration = -1;
else