diff options
-rw-r--r-- | DOCS/man/vo.rst | 6 | ||||
-rw-r--r-- | video/out/vo_opengl_cb.c | 32 |
2 files changed, 31 insertions, 7 deletions
diff --git a/DOCS/man/vo.rst b/DOCS/man/vo.rst index 6e1d89fade..874e064145 100644 --- a/DOCS/man/vo.rst +++ b/DOCS/man/vo.rst @@ -898,13 +898,15 @@ Available video output drivers are: ``frame-queue-size=<1..100>`` The maximum count of frames which the frame queue can hold (default: 1) - ``frame-drop-mode=<pop|clear>`` + ``frame-drop-mode=<pop|clear|block>`` Select the behavior when the frame queue is full. pop - Drop the oldest frame in the frame queue. (default) + Drop the oldest frame in the frame queue. clear Drop all frames in the frame queue. + block + Wait for a short time, behave like ``clear`` on timeout. (default) This also supports many of the suboptions the ``opengl`` VO has. Run ``mpv --vo=opengl-cb:help`` for a list. 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}, }; |