summaryrefslogtreecommitdiffstats
path: root/video/out/vo_libmpv.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/vo_libmpv.c')
-rw-r--r--video/out/vo_libmpv.c168
1 files changed, 87 insertions, 81 deletions
diff --git a/video/out/vo_libmpv.c b/video/out/vo_libmpv.c
index d07ab4c4eb..7974eed3f7 100644
--- a/video/out/vo_libmpv.c
+++ b/video/out/vo_libmpv.c
@@ -1,13 +1,11 @@
+#include <assert.h>
+#include <limits.h>
+#include <math.h>
+#include <stdatomic.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <math.h>
-#include <stdbool.h>
-#include <limits.h>
-#include <pthread.h>
-#include <assert.h>
-
-#include "config.h"
#include "mpv_talloc.h"
#include "common/common.h"
@@ -21,7 +19,7 @@
#include "vo.h"
#include "video/mp_image.h"
#include "sub/osd.h"
-#include "osdep/atomic.h"
+#include "osdep/threads.h"
#include "osdep/timer.h"
#include "common/global.h"
@@ -29,6 +27,10 @@
#include "libmpv.h"
+#if HAVE_MACOS_COCOA_CB
+#include "osdep/mac/app_bridge.h"
+#endif
+
/*
* mpv_render_context is managed by the host application - the host application
* can access it any time, even if the VO is destroyed (or not created yet).
@@ -67,20 +69,20 @@ struct mpv_render_context {
bool advanced_control;
struct dr_helper *dr; // NULL if advanced_control disabled
- pthread_mutex_t control_lock;
+ mp_mutex control_lock;
// --- Protected by control_lock
mp_render_cb_control_fn control_cb;
void *control_cb_ctx;
- pthread_mutex_t update_lock;
- pthread_cond_t update_cond; // paired with update_lock
+ mp_mutex update_lock;
+ mp_cond update_cond; // paired with update_lock
// --- Protected by update_lock
mpv_render_update_fn update_cb;
void *update_cb_ctx;
- pthread_mutex_t lock;
- pthread_cond_t video_wait; // paired with lock
+ mp_mutex lock;
+ mp_cond video_wait; // paired with lock
// --- Protected by lock
struct vo_frame *next_frame; // next frame to draw
@@ -117,12 +119,12 @@ const struct render_backend_fns *render_backends[] = {
static void update(struct mpv_render_context *ctx)
{
- pthread_mutex_lock(&ctx->update_lock);
+ mp_mutex_lock(&ctx->update_lock);
if (ctx->update_cb)
ctx->update_cb(ctx->update_cb_ctx);
- pthread_cond_broadcast(&ctx->update_cond);
- pthread_mutex_unlock(&ctx->update_lock);
+ mp_cond_broadcast(&ctx->update_cond);
+ mp_mutex_unlock(&ctx->update_lock);
}
void *get_mpv_render_param(mpv_render_param *params, mpv_render_param_type type,
@@ -137,7 +139,7 @@ void *get_mpv_render_param(mpv_render_param *params, mpv_render_param_type type,
static void forget_frames(struct mpv_render_context *ctx, bool all)
{
- pthread_cond_broadcast(&ctx->video_wait);
+ mp_cond_broadcast(&ctx->video_wait);
if (all) {
talloc_free(ctx->cur_frame);
ctx->cur_frame = NULL;
@@ -152,22 +154,22 @@ static void dispatch_wakeup(void *ptr)
}
static struct mp_image *render_get_image(void *ptr, int imgfmt, int w, int h,
- int stride_align)
+ int stride_align, int flags)
{
struct mpv_render_context *ctx = ptr;
- return ctx->renderer->fns->get_image(ctx->renderer, imgfmt, w, h, stride_align);
+ return ctx->renderer->fns->get_image(ctx->renderer, imgfmt, w, h, stride_align, flags);
}
int mpv_render_context_create(mpv_render_context **res, mpv_handle *mpv,
mpv_render_param *params)
{
mpv_render_context *ctx = talloc_zero(NULL, mpv_render_context);
- pthread_mutex_init(&ctx->control_lock, NULL);
- pthread_mutex_init(&ctx->lock, NULL);
- pthread_mutex_init(&ctx->update_lock, NULL);
- pthread_cond_init(&ctx->update_cond, NULL);
- pthread_cond_init(&ctx->video_wait, NULL);
+ mp_mutex_init(&ctx->control_lock);
+ mp_mutex_init(&ctx->lock);
+ mp_mutex_init(&ctx->update_lock);
+ mp_cond_init(&ctx->update_cond);
+ mp_cond_init(&ctx->video_wait);
ctx->global = mp_client_get_global(mpv);
ctx->client_api = ctx->global->client_api;
@@ -229,22 +231,22 @@ void mpv_render_context_set_update_callback(mpv_render_context *ctx,
mpv_render_update_fn callback,
void *callback_ctx)
{
- pthread_mutex_lock(&ctx->update_lock);
+ mp_mutex_lock(&ctx->update_lock);
ctx->update_cb = callback;
ctx->update_cb_ctx = callback_ctx;
if (ctx->update_cb)
ctx->update_cb(ctx->update_cb_ctx);
- pthread_mutex_unlock(&ctx->update_lock);
+ mp_mutex_unlock(&ctx->update_lock);
}
void mp_render_context_set_control_callback(mpv_render_context *ctx,
mp_render_cb_control_fn callback,
void *callback_ctx)
{
- pthread_mutex_lock(&ctx->control_lock);
+ mp_mutex_lock(&ctx->control_lock);
ctx->control_cb = callback;
ctx->control_cb_ctx = callback_ctx;
- pthread_mutex_unlock(&ctx->control_lock);
+ mp_mutex_unlock(&ctx->control_lock);
}
void mpv_render_context_free(mpv_render_context *ctx)
@@ -284,13 +286,13 @@ void mpv_render_context_free(mpv_render_context *ctx)
}
}
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
// Barrier - guarantee uninit() has left the lock region. It will access ctx
// until the lock has been released, so we must not proceed with destruction
// before we can acquire the lock. (The opposite, uninit() acquiring the
// lock, can not happen anymore at this point - we've waited for VO uninit,
// and prevented that new VOs can be created.)
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
assert(!atomic_load(&ctx->in_use));
assert(!ctx->vo);
@@ -313,11 +315,11 @@ void mpv_render_context_free(mpv_render_context *ctx)
talloc_free(ctx->dr);
talloc_free(ctx->dispatch);
- pthread_cond_destroy(&ctx->update_cond);
- pthread_cond_destroy(&ctx->video_wait);
- pthread_mutex_destroy(&ctx->update_lock);
- pthread_mutex_destroy(&ctx->lock);
- pthread_mutex_destroy(&ctx->control_lock);
+ mp_cond_destroy(&ctx->update_cond);
+ mp_cond_destroy(&ctx->video_wait);
+ mp_mutex_destroy(&ctx->update_lock);
+ mp_mutex_destroy(&ctx->lock);
+ mp_mutex_destroy(&ctx->control_lock);
talloc_free(ctx);
}
@@ -333,7 +335,7 @@ bool mp_render_context_acquire(mpv_render_context *ctx)
int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params)
{
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
int do_render =
!GET_MPV_RENDER_PARAM(params, MPV_RENDER_PARAM_SKIP_RENDERING, int, 0);
@@ -343,7 +345,7 @@ int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params)
int err = ctx->renderer->fns->get_target_size(ctx->renderer, params,
&vp_w, &vp_h);
if (err < 0) {
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return err;
}
@@ -387,7 +389,7 @@ int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params)
ctx->next_frame = NULL;
if (!(frame->redraw || !frame->current))
wait_present_count += 1;
- pthread_cond_broadcast(&ctx->video_wait);
+ mp_cond_broadcast(&ctx->video_wait);
talloc_free(ctx->cur_frame);
ctx->cur_frame = vo_frame_ref(frame);
} else {
@@ -400,7 +402,7 @@ int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params)
if (!frame)
frame = &dummy;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
MP_STATS(ctx, "glcb-render");
@@ -415,10 +417,10 @@ int mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params)
if (GET_MPV_RENDER_PARAM(params, MPV_RENDER_PARAM_BLOCK_FOR_TARGET_TIME,
int, 1))
{
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
while (wait_present_count > ctx->present_count)
- pthread_cond_wait(&ctx->video_wait, &ctx->lock);
- pthread_mutex_unlock(&ctx->lock);
+ mp_cond_wait(&ctx->video_wait, &ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
}
return err;
@@ -428,10 +430,10 @@ void mpv_render_context_report_swap(mpv_render_context *ctx)
{
MP_STATS(ctx, "glcb-reportflip");
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
ctx->flip_count += 1;
- pthread_cond_broadcast(&ctx->video_wait);
- pthread_mutex_unlock(&ctx->lock);
+ mp_cond_broadcast(&ctx->video_wait);
+ mp_mutex_unlock(&ctx->lock);
}
uint64_t mpv_render_context_update(mpv_render_context *ctx)
@@ -440,10 +442,10 @@ uint64_t mpv_render_context_update(mpv_render_context *ctx)
mp_dispatch_queue_process(ctx->dispatch, 0);
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
if (ctx->next_frame)
res |= MPV_RENDER_UPDATE_FRAME;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return res;
}
@@ -457,7 +459,7 @@ int mpv_render_context_get_info(mpv_render_context *ctx,
mpv_render_param param)
{
int res = MPV_ERROR_NOT_IMPLEMENTED;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
switch (param.type) {
case MPV_RENDER_PARAM_NEXT_FRAME_INFO: {
@@ -479,7 +481,7 @@ int mpv_render_context_get_info(mpv_render_context *ctx,
default:;
}
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return res;
}
@@ -488,12 +490,12 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
struct vo_priv *p = vo->priv;
struct mpv_render_context *ctx = p->ctx;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
assert(!ctx->next_frame);
ctx->next_frame = vo_frame_ref(frame);
ctx->expected_flip_count = ctx->flip_count + 1;
ctx->redrawing = frame->redraw || !frame->current;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
update(ctx);
}
@@ -502,13 +504,13 @@ static void flip_page(struct vo *vo)
{
struct vo_priv *p = vo->priv;
struct mpv_render_context *ctx = p->ctx;
- struct timespec ts = mp_rel_time_to_timespec(0.2);
+ int64_t until = mp_time_ns() + MP_TIME_MS_TO_NS(200);
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
// Wait until frame was rendered
while (ctx->next_frame) {
- if (pthread_cond_timedwait(&ctx->video_wait, &ctx->lock, &ts)) {
+ if (mp_cond_timedwait_until(&ctx->video_wait, &ctx->lock, until)) {
if (ctx->next_frame) {
MP_VERBOSE(vo, "mpv_render_context_render() not being called "
"or stuck.\n");
@@ -519,7 +521,7 @@ static void flip_page(struct vo *vo)
// Unblock mpv_render_context_render().
ctx->present_count += 1;
- pthread_cond_broadcast(&ctx->video_wait);
+ mp_cond_broadcast(&ctx->video_wait);
if (ctx->redrawing)
goto done; // do not block for redrawing
@@ -530,7 +532,7 @@ static void flip_page(struct vo *vo)
// Assume the user calls it consistently _if_ it's called at all.
if (!ctx->flip_count)
break;
- if (pthread_cond_timedwait(&ctx->video_wait, &ctx->lock, &ts)) {
+ if (mp_cond_timedwait_until(&ctx->video_wait, &ctx->lock, until)) {
MP_VERBOSE(vo, "mpv_render_report_swap() not being called.\n");
goto done;
}
@@ -544,11 +546,11 @@ done:
ctx->cur_frame = ctx->next_frame;
ctx->next_frame = NULL;
ctx->present_count += 2;
- pthread_cond_signal(&ctx->video_wait);
+ mp_cond_signal(&ctx->video_wait);
vo_increment_drop_count(vo, 1);
}
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
}
static int query_format(struct vo *vo, int format)
@@ -557,10 +559,10 @@ static int query_format(struct vo *vo, int format)
struct mpv_render_context *ctx = p->ctx;
bool ok = false;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
if (format >= IMGFMT_START && format < IMGFMT_END)
ok = ctx->imgfmt_supported[format - IMGFMT_START];
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return ok;
}
@@ -574,9 +576,9 @@ static void run_control_on_render_thread(void *p)
switch (request) {
case VOCTRL_SCREENSHOT: {
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
struct vo_frame *frame = vo_frame_ref(ctx->cur_frame);
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
if (frame && ctx->renderer->fns->screenshot)
ctx->renderer->fns->screenshot(ctx->renderer, frame, data);
talloc_free(frame);
@@ -601,28 +603,25 @@ static int control(struct vo *vo, uint32_t request, void *data)
switch (request) {
case VOCTRL_RESET:
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
forget_frames(ctx, false);
ctx->need_reset = true;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
vo->want_redraw = true;
return VO_TRUE;
case VOCTRL_PAUSE:
vo->want_redraw = true;
return VO_TRUE;
- case VOCTRL_SET_EQUALIZER:
- vo->want_redraw = true;
- return VO_TRUE;
case VOCTRL_SET_PANSCAN:
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
ctx->need_resize = true;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
vo->want_redraw = true;
return VO_TRUE;
case VOCTRL_UPDATE_RENDER_OPTS:
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
ctx->need_update_external = true;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
vo->want_redraw = true;
return VO_TRUE;
}
@@ -641,26 +640,26 @@ static int control(struct vo *vo, uint32_t request, void *data)
}
int r = VO_NOTIMPL;
- pthread_mutex_lock(&ctx->control_lock);
+ mp_mutex_lock(&ctx->control_lock);
if (ctx->control_cb) {
int events = 0;
r = p->ctx->control_cb(vo, p->ctx->control_cb_ctx,
&events, request, data);
vo_event(vo, events);
}
- pthread_mutex_unlock(&ctx->control_lock);
+ mp_mutex_unlock(&ctx->control_lock);
return r;
}
static struct mp_image *get_image(struct vo *vo, int imgfmt, int w, int h,
- int stride_align)
+ int stride_align, int flags)
{
struct vo_priv *p = vo->priv;
struct mpv_render_context *ctx = p->ctx;
if (ctx->dr)
- return dr_helper_get_image(ctx->dr, imgfmt, w, h, stride_align);
+ return dr_helper_get_image(ctx->dr, imgfmt, w, h, stride_align, flags);
return NULL;
}
@@ -670,12 +669,12 @@ static int reconfig(struct vo *vo, struct mp_image_params *params)
struct vo_priv *p = vo->priv;
struct mpv_render_context *ctx = p->ctx;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
forget_frames(ctx, true);
ctx->img_params = *params;
ctx->need_reconfig = true;
ctx->need_resize = true;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
control(vo, VOCTRL_RECONFIG, NULL);
@@ -689,7 +688,7 @@ static void uninit(struct vo *vo)
control(vo, VOCTRL_UNINIT, NULL);
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
forget_frames(ctx, true);
ctx->img_params = (struct mp_image_params){0};
@@ -705,11 +704,18 @@ static void uninit(struct vo *vo)
assert(prev_in_use); // obviously must have been set
mp_dispatch_interrupt(ctx->dispatch);
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
}
static int preinit(struct vo *vo)
{
+#if HAVE_MACOS_COCOA_CB
+ cocoa_init_cocoa_cb();
+#else
+ if (vo->probing)
+ return -1;
+#endif
+
struct vo_priv *p = vo->priv;
struct mpv_render_context *ctx =
@@ -722,11 +728,11 @@ static int preinit(struct vo *vo)
return -1;
}
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
ctx->vo = vo;
ctx->need_resize = true;
ctx->need_update_external = true;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
vo->hwdec_devs = ctx->hwdec_devs;
control(vo, VOCTRL_PREINIT, NULL);