summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-05-12 22:16:19 +0200
committerwm4 <wm4@nowhere>2015-05-12 22:16:19 +0200
commitee3de1a063c281c1c915f204756d518966afdd54 (patch)
treef7a6d67353b451e93637965e07e4739a17871a83 /video/out
parent4d9255a5e1a1c5be805800070a79ef1bcc1a150a (diff)
downloadmpv-ee3de1a063c281c1c915f204756d518966afdd54.tar.bz2
mpv-ee3de1a063c281c1c915f204756d518966afdd54.tar.xz
vo_opengl_cb: add a "block" framedrop mode and make it default
(I have no idea why there are different modes.) Instead of risking to drop frames too early, give it some margin. Since there are situations this could deadlock, wait with a timeout. This can happen if e.g. the API user is refusing to render anything, or if uninitialization is happening.
Diffstat (limited to 'video/out')
-rw-r--r--video/out/vo_opengl_cb.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c
index ad8487ebaf..77bf5ed025 100644
--- a/video/out/vo_opengl_cb.c
+++ b/video/out/vo_opengl_cb.c
@@ -39,6 +39,7 @@
#define FRAME_DROP_POP 0 // drop the oldest frame in queue
#define FRAME_DROP_CLEAR 1 // drop all frames in queue
+#define FRAME_DROP_BLOCK 2
struct vo_priv {
struct vo *vo;
@@ -57,6 +58,7 @@ struct mpv_opengl_cb_context {
struct mp_client_api *client_api;
pthread_mutex_t lock;
+ pthread_cond_t wakeup;
// --- Protected by lock
bool initialized;
@@ -104,6 +106,7 @@ static struct mp_image *frame_queue_pop(struct mpv_opengl_cb_context *ctx)
return NULL;
struct mp_image *ret = ctx->frame_queue[0];
MP_TARRAY_REMOVE_AT(ctx->frame_queue, ctx->queued_frames, 0);
+ pthread_cond_broadcast(&ctx->wakeup);
return ret;
}
@@ -114,6 +117,7 @@ static void frame_queue_drop(struct mpv_opengl_cb_context *ctx)
talloc_free(mpi);
if (ctx->active)
vo_increment_drop_count(ctx->active, 1);
+ pthread_cond_broadcast(&ctx->wakeup);
}
}
@@ -124,6 +128,7 @@ static void frame_queue_clear(struct mpv_opengl_cb_context *ctx)
talloc_free(ctx->frame_queue);
ctx->frame_queue = NULL;
ctx->queued_frames = 0;
+ pthread_cond_broadcast(&ctx->wakeup);
}
static void frame_queue_drop_all(struct mpv_opengl_cb_context *ctx)
@@ -132,21 +137,25 @@ static void frame_queue_drop_all(struct mpv_opengl_cb_context *ctx)
frame_queue_clear(ctx);
if (ctx->active && frames > 0)
vo_increment_drop_count(ctx->active, frames);
+ pthread_cond_broadcast(&ctx->wakeup);
}
static void frame_queue_push(struct mpv_opengl_cb_context *ctx, struct mp_image *mpi)
{
MP_TARRAY_APPEND(ctx, ctx->frame_queue, ctx->queued_frames, mpi);
+ pthread_cond_broadcast(&ctx->wakeup);
}
static void frame_queue_shrink(struct mpv_opengl_cb_context *ctx, int size)
{
+ pthread_cond_broadcast(&ctx->wakeup);
while (ctx->queued_frames > size)
frame_queue_drop(ctx);
}
static void forget_frames(struct mpv_opengl_cb_context *ctx)
{
+ pthread_cond_broadcast(&ctx->wakeup);
frame_queue_clear(ctx);
mp_image_unrefp(&ctx->waiting_frame);
}
@@ -159,6 +168,7 @@ static void free_ctx(void *ptr)
// mpv_opengl_cb_uninit_gl() properly.
assert(!ctx->initialized);
+ pthread_cond_destroy(&ctx->wakeup);
pthread_mutex_destroy(&ctx->lock);
}
@@ -168,6 +178,7 @@ struct mpv_opengl_cb_context *mp_opengl_create(struct mpv_global *g,
mpv_opengl_cb_context *ctx = talloc_zero(NULL, mpv_opengl_cb_context);
talloc_set_destructor(ctx, free_ctx);
pthread_mutex_init(&ctx->lock, NULL);
+ pthread_cond_init(&ctx->wakeup, NULL);
ctx->gl = talloc_zero(ctx, GL);
@@ -374,11 +385,20 @@ static void flip_page(struct vo *vo)
struct vo_priv *p = vo->priv;
pthread_mutex_lock(&p->ctx->lock);
- if (p->ctx->queued_frames >= p->frame_queue_size) {
- if (p->frame_drop_mode == FRAME_DROP_CLEAR)
+ while (p->ctx->queued_frames >= p->frame_queue_size) {
+ switch (p->frame_drop_mode) {
+ case FRAME_DROP_CLEAR:
frame_queue_drop_all(p->ctx);
- else // FRAME_DROP_POP mode
+ break;
+ case FRAME_DROP_POP:
frame_queue_shrink(p->ctx, p->frame_queue_size - 1);
+ break;
+ case FRAME_DROP_BLOCK: ;
+ struct timespec ts = mp_rel_time_to_timespec(0.2);
+ if (pthread_cond_timedwait(&p->ctx->wakeup, &p->ctx->lock, &ts))
+ frame_queue_drop_all(p->ctx);
+ break;
+ }
}
frame_queue_push(p->ctx, p->ctx->waiting_frame);
p->ctx->waiting_frame = NULL;
@@ -418,7 +438,8 @@ static const struct m_option change_opts[] = {
OPT_INTRANGE("frame-queue-size", frame_queue_size, 0, 1, 100, OPTDEF_INT(2)),
OPT_CHOICE("frame-drop-mode", frame_drop_mode, 0,
({"pop", FRAME_DROP_POP},
- {"clear", FRAME_DROP_CLEAR})),
+ {"clear", FRAME_DROP_CLEAR},
+ {"block", FRAME_DROP_BLOCK})),
OPT_SUBSTRUCT("", renderer_opts, gl_video_conf, 0),
{0}
};
@@ -555,7 +576,8 @@ static const struct m_option options[] = {
OPT_INTRANGE("frame-queue-size", frame_queue_size, 0, 1, 100, OPTDEF_INT(2)),
OPT_CHOICE("frame-drop-mode", frame_drop_mode, 0,
({"pop", FRAME_DROP_POP},
- {"clear", FRAME_DROP_CLEAR})),
+ {"clear", FRAME_DROP_CLEAR},
+ {"block", FRAME_DROP_BLOCK}), OPTDEF_INT(FRAME_DROP_BLOCK)),
OPT_SUBSTRUCT("", renderer_opts, gl_video_conf, 0),
{0},
};