summaryrefslogtreecommitdiffstats
path: root/video/out/vo_sdl.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-08-12 23:02:08 +0200
committerwm4 <wm4@nowhere>2014-08-12 23:24:08 +0200
commitdf58e822377af0a3802bba862de80eafaea732cb (patch)
tree05a5bfc611612c4397bdaec4c9127c537498bcec /video/out/vo_sdl.c
parenta1be3cf147e18a49c88c613d65478ede9676a744 (diff)
downloadmpv-df58e822377af0a3802bba862de80eafaea732cb.tar.bz2
mpv-df58e822377af0a3802bba862de80eafaea732cb.tar.xz
video: move display and timing to a separate thread
The VO is run inside its own thread. It also does most of video timing. The playloop hands the image data and a realtime timestamp to the VO, and the VO does the rest. In particular, this allows the playloop to do other things, instead of blocking for video redraw. But if anything accesses the VO during video timing, it will block. This also fixes vo_sdl.c event handling; but that is only a side-effect, since reimplementing the broken way would require more effort. Also drop --softsleep. In theory, this option helps if the kernel's sleeping mechanism is too inaccurate for video timing. In practice, I haven't ever encountered a situation where it helps, and it just burns CPU cycles. On the other hand it's probably actively harmful, because it prevents the libavcodec decoder threads from doing real work. Side note: Originally, I intended that multiple frames can be queued to the VO. But this is not done, due to problems with OSD and other certain features. OSD in particular is simply designed in a way that it can be neither timed nor copied, so you do have to render it into the video frame before you can draw the next frame. (Subtitles have no such restriction. sd_lavc was even updated to fix this.) It seems the right solution to queuing multiple VO frames is rendering on VO-backed framebuffers, like vo_vdpau.c does. This requires VO driver support, and is out of scope of this commit. As consequence, the VO has a queue size of 1. The existing video queue is just needed to compute frame duration, and will be moved out in the next commit.
Diffstat (limited to 'video/out/vo_sdl.c')
-rw-r--r--video/out/vo_sdl.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/video/out/vo_sdl.c b/video/out/vo_sdl.c
index ee8e0d879a..3c6a653208 100644
--- a/video/out/vo_sdl.c
+++ b/video/out/vo_sdl.c
@@ -193,6 +193,7 @@ struct priv {
double osd_pts;
int mouse_hidden;
int brightness, contrast;
+ Uint32 wakeup_event;
// options
int allow_sw;
@@ -392,6 +393,7 @@ static void resize(struct vo *vo, int w, int h)
&vc->osd_res);
SDL_RenderSetLogicalSize(vc->renderer, w, h);
vo->want_redraw = true;
+ vo_wakeup(vo);
}
static void force_resize(struct vo *vo)
@@ -535,11 +537,22 @@ static void flip_page(struct vo *vo)
SDL_RenderPresent(vc->renderer);
}
-static void check_events(struct vo *vo)
+static void wakeup(struct vo *vo)
{
+ struct priv *vc = vo->priv;
+ SDL_Event event = {.type = vc->wakeup_event};
+ // Note that there is no context - SDL is a singleton.
+ SDL_PushEvent(&event);
+}
+
+static int wait_events(struct vo *vo, int64_t until_time_us)
+{
+ int64_t wait_us = until_time_us - mp_time_us();
+ int timeout_ms = MPCLAMP((wait_us + 500) / 1000, 0, 10000);
SDL_Event ev;
- while (SDL_PollEvent(&ev)) {
+ while (SDL_WaitEventTimeout(&ev, timeout_ms)) {
+ timeout_ms = 0;
switch (ev.type) {
case SDL_WINDOWEVENT:
switch (ev.window.event) {
@@ -617,6 +630,8 @@ static void check_events(struct vo *vo)
break;
}
}
+
+ return 0;
}
static void uninit(struct vo *vo)
@@ -824,8 +839,9 @@ static int preinit(struct vo *vo)
// please reinitialize the renderer to proper size on config()
vc->reinit_renderer = true;
- // we don't have proper event handling
- vo->wakeup_period = 0.2;
+ vc->wakeup_event = SDL_RegisterEvents(1);
+ if (vc->wakeup_event == (Uint32)-1)
+ MP_ERR(vo, "SDL_RegisterEvents() failed.\n");
return 0;
}
@@ -983,9 +999,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
struct priv *vc = vo->priv;
switch (request) {
- case VOCTRL_CHECK_EVENTS:
- check_events(vo);
- return 1;
case VOCTRL_FULLSCREEN:
set_fullscreen(vo);
return 1;
@@ -1047,4 +1060,6 @@ const struct vo_driver video_out_sdl = {
.draw_image = draw_image,
.uninit = uninit,
.flip_page = flip_page,
+ .wait_events = wait_events,
+ .wakeup = wakeup,
};