summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
Diffstat (limited to 'video')
-rw-r--r--video/decode/d3d.c36
-rw-r--r--video/decode/hw_d3d11va.c47
-rw-r--r--video/decode/hw_dxva2.c36
-rw-r--r--video/decode/lavc.h4
-rw-r--r--video/decode/vd_lavc.c35
-rw-r--r--video/hwdec.c13
-rw-r--r--video/hwdec.h16
-rw-r--r--video/vaapi.c95
-rw-r--r--video/vaapi.h4
-rw-r--r--video/vdpau.c119
-rw-r--r--video/vdpau.h5
11 files changed, 207 insertions, 203 deletions
diff --git a/video/decode/d3d.c b/video/decode/d3d.c
index cab878bafe..a9b67eb0a9 100644
--- a/video/decode/d3d.c
+++ b/video/decode/d3d.c
@@ -124,8 +124,38 @@ static void d3d11_complete_image_params(struct mp_image *img)
mp_image_setfmt(img, IMGFMT_D3D11NV12);
}
+static struct AVBufferRef *d3d11_create_standalone(struct mpv_global *global,
+ struct mp_log *plog, struct hwcontext_create_dev_params *params)
+{
+ ID3D11Device *device = NULL;
+ HRESULT hr;
+
+ d3d_load_dlls();
+ if (!d3d11_D3D11CreateDevice) {
+ mp_err(plog, "Failed to load D3D11 library\n");
+ return NULL;
+ }
+
+ hr = d3d11_D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL,
+ D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0,
+ D3D11_SDK_VERSION, &device, NULL, NULL);
+ if (FAILED(hr)) {
+ mp_err(plog, "Failed to create D3D11 Device: %s\n",
+ mp_HRESULT_to_str(hr));
+ return NULL;
+ }
+
+ AVBufferRef *avref = d3d11_wrap_device_ref(device);
+ ID3D11Device_Release(device);
+ if (!avref)
+ mp_err(plog, "Failed to allocate AVHWDeviceContext.\n");
+
+ return avref;
+}
+
const struct hwcontext_fns hwcontext_fns_d3d11 = {
- .av_hwdevice_type = AV_HWDEVICE_TYPE_D3D11VA,
- .complete_image_params = d3d11_complete_image_params,
- .refine_hwframes = d3d11_refine_hwframes,
+ .av_hwdevice_type = AV_HWDEVICE_TYPE_D3D11VA,
+ .complete_image_params = d3d11_complete_image_params,
+ .refine_hwframes = d3d11_refine_hwframes,
+ .create_dev = d3d11_create_standalone,
};
diff --git a/video/decode/hw_d3d11va.c b/video/decode/hw_d3d11va.c
index cc1d122f59..76af9a52a9 100644
--- a/video/decode/hw_d3d11va.c
+++ b/video/decode/hw_d3d11va.c
@@ -33,50 +33,6 @@
#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_d3d11va.h>
-static void d3d11_destroy_dev(struct mp_hwdec_ctx *ctx)
-{
- av_buffer_unref(&ctx->av_device_ref);
- ID3D11Device_Release((ID3D11Device *)ctx->ctx);
- talloc_free(ctx);
-}
-
-static struct mp_hwdec_ctx *d3d11_create_dev(struct mpv_global *global,
- struct mp_log *plog, bool probing)
-{
- ID3D11Device *device = NULL;
- HRESULT hr;
-
- d3d_load_dlls();
- if (!d3d11_D3D11CreateDevice) {
- mp_err(plog, "Failed to load D3D11 library\n");
- return NULL;
- }
-
- hr = d3d11_D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL,
- D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0,
- D3D11_SDK_VERSION, &device, NULL, NULL);
- if (FAILED(hr)) {
- mp_err(plog, "Failed to create D3D11 Device: %s\n",
- mp_HRESULT_to_str(hr));
- return NULL;
- }
-
- struct mp_hwdec_ctx *ctx = talloc_ptrtype(NULL, ctx);
- *ctx = (struct mp_hwdec_ctx) {
- .type = HWDEC_D3D11VA_COPY,
- .ctx = device,
- .destroy = d3d11_destroy_dev,
- .av_device_ref = d3d11_wrap_device_ref(device),
- };
-
- if (!ctx->av_device_ref) {
- mp_err(plog, "Failed to allocate AVHWDeviceContext.\n");
- d3d11_destroy_dev(ctx);
- return NULL;
- }
-
- return ctx;
-}
const struct vd_lavc_hwdec mp_vd_lavc_d3d11va = {
.type = HWDEC_D3D11VA,
@@ -90,7 +46,8 @@ const struct vd_lavc_hwdec mp_vd_lavc_d3d11va_copy = {
.copying = true,
.image_format = IMGFMT_D3D11VA,
.generic_hwaccel = true,
- .create_dev = d3d11_create_dev,
+ .create_standalone_dev = true,
+ .create_standalone_dev_type = AV_HWDEVICE_TYPE_D3D11VA,
.set_hwframes = true,
.delay_queue = HWDEC_DELAY_QUEUE_COUNT,
};
diff --git a/video/decode/hw_dxva2.c b/video/decode/hw_dxva2.c
index 37b2b78003..ede494ff4f 100644
--- a/video/decode/hw_dxva2.c
+++ b/video/decode/hw_dxva2.c
@@ -88,15 +88,8 @@ fail:
return NULL;
}
-static void d3d9_destroy_dev(struct mp_hwdec_ctx *ctx)
-{
- av_buffer_unref(&ctx->av_device_ref);
- IDirect3DDevice9_Release((IDirect3DDevice9 *)ctx->ctx);
- talloc_free(ctx);
-}
-
-static struct mp_hwdec_ctx *d3d9_create_dev(struct mpv_global *global,
- struct mp_log *plog, bool probing)
+static struct AVBufferRef *d3d9_create_standalone(struct mpv_global *global,
+ struct mp_log *plog, struct hwcontext_create_dev_params *params)
{
d3d_load_dlls();
if (!d3d9_dll || !dxva2_dll) {
@@ -149,23 +142,19 @@ static struct mp_hwdec_ctx *d3d9_create_dev(struct mpv_global *global,
return NULL;
}
- struct mp_hwdec_ctx *ctx = talloc_ptrtype(NULL, ctx);
- *ctx = (struct mp_hwdec_ctx) {
- .type = HWDEC_D3D11VA_COPY,
- .ctx = exdev,
- .destroy = d3d9_destroy_dev,
- .av_device_ref = d3d9_wrap_device_ref((IDirect3DDevice9 *)exdev),
- };
-
- if (!ctx->av_device_ref) {
+ AVBufferRef *avref = d3d9_wrap_device_ref((IDirect3DDevice9 *)exdev);
+ IDirect3DDevice9Ex_Release(exdev);
+ if (!avref)
mp_err(plog, "Failed to allocate AVHWDeviceContext.\n");
- d3d9_destroy_dev(ctx);
- return NULL;
- }
- return ctx;
+ return avref;
}
+const struct hwcontext_fns hwcontext_fns_dxva2 = {
+ .av_hwdevice_type = AV_HWDEVICE_TYPE_DXVA2,
+ .create_dev = d3d9_create_standalone,
+};
+
const struct vd_lavc_hwdec mp_vd_lavc_dxva2 = {
.type = HWDEC_DXVA2,
.image_format = IMGFMT_DXVA2,
@@ -178,7 +167,8 @@ const struct vd_lavc_hwdec mp_vd_lavc_dxva2_copy = {
.copying = true,
.image_format = IMGFMT_DXVA2,
.generic_hwaccel = true,
- .create_dev = d3d9_create_dev,
+ .create_standalone_dev = true,
+ .create_standalone_dev_type = AV_HWDEVICE_TYPE_DXVA2,
.set_hwframes = true,
.delay_queue = HWDEC_DELAY_QUEUE_COUNT,
};
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index b427ae17a2..114e454c54 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -97,10 +97,6 @@ struct vd_lavc_hwdec {
int (*init)(struct lavc_ctx *ctx);
int (*init_decoder)(struct lavc_ctx *ctx);
void (*uninit)(struct lavc_ctx *ctx);
- // For copy hwdecs. If probing is true, don't log errors if unavailable.
- // The returned device will be freed with mp_hwdec_ctx->destroy.
- struct mp_hwdec_ctx *(*create_dev)(struct mpv_global *global,
- struct mp_log *log, bool probing);
// Suffix for libavcodec decoder. If non-NULL, the codec is overridden
// with hwdec_find_decoder.
// Intuitively, this will force the corresponding wrapper decoder.
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 90217f5b8d..1097577c05 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -200,7 +200,8 @@ static const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy = {
.image_format = IMGFMT_VAAPI,
.generic_hwaccel = true,
.set_hwframes = true,
- .create_dev = va_create_standalone,
+ .create_standalone_dev = true,
+ .create_standalone_dev_type = AV_HWDEVICE_TYPE_VAAPI,
};
#endif
@@ -220,7 +221,8 @@ static const struct vd_lavc_hwdec mp_vd_lavc_vdpau_copy = {
.image_format = IMGFMT_VDPAU,
.generic_hwaccel = true,
.set_hwframes = true,
- .create_dev = vdpau_create_standalone,
+ .create_standalone_dev = true,
+ .create_standalone_dev_type = AV_HWDEVICE_TYPE_VDPAU,
};
#endif
@@ -358,16 +360,27 @@ static struct mp_hwdec_ctx *hwdec_create_dev(struct dec_video *vd,
.ctx = NULL,
.destroy = standalone_dev_destroy,
};
- if (av_hwdevice_ctx_create(&ctx->av_device_ref,
+ const struct hwcontext_fns *fns =
+ hwdec_get_hwcontext_fns(hwdec->create_standalone_dev_type);
+ if (fns && fns->create_dev) {
+ struct hwcontext_create_dev_params params = {
+ .probing = autoprobe,
+ };
+ ctx->av_device_ref = fns->create_dev(vd->global, vd->log, &params);
+ if (!ctx->av_device_ref) {
+ standalone_dev_destroy(ctx);
+ ctx = NULL;
+ }
+ } else {
+ if (av_hwdevice_ctx_create(&ctx->av_device_ref,
hwdec->create_standalone_dev_type, NULL, NULL, 0) < 0)
- {
- standalone_dev_destroy(ctx);
- ctx = NULL;
+ {
+ standalone_dev_destroy(ctx);
+ ctx = NULL;
+ }
}
return ctx;
}
- if (hwdec->create_dev)
- return hwdec->create_dev(vd->global, vd->log, autoprobe);
if (vd->hwdec_devs) {
int type = hwdec->interop_type ? hwdec->interop_type : hwdec->type;
hwdec_devices_request_all(vd->hwdec_devs);
@@ -391,8 +404,7 @@ static int hwdec_probe(struct dec_video *vd, struct vd_lavc_hwdec *hwdec,
return hwdec->copying ? -1 : HWDEC_ERR_NO_CTX;
if (dev->emulated)
r = HWDEC_ERR_EMULATED;
- bool owns_hwdec_dev = !!hwdec->create_dev ||
- hwdec->create_standalone_dev;
+ bool owns_hwdec_dev = !!hwdec->create_standalone_dev;
if (owns_hwdec_dev && dev->destroy)
dev->destroy(dev);
}
@@ -594,8 +606,7 @@ static void init_avctx(struct dec_video *vd, const char *decoder,
ctx->hwdec_dev = hwdec_create_dev(vd, ctx->hwdec, false);
if (!ctx->hwdec_dev)
goto error;
- ctx->owns_hwdec_dev = !!ctx->hwdec->create_dev ||
- ctx->hwdec->create_standalone_dev;
+ ctx->owns_hwdec_dev = ctx->hwdec->create_standalone_dev;
if (ctx->hwdec_dev->restore_device)
ctx->hwdec_dev->restore_device(ctx->hwdec_dev);
if (!ctx->hwdec->set_hwframes)
diff --git a/video/hwdec.c b/video/hwdec.c
index 31df1522ce..04f7d46d9a 100644
--- a/video/hwdec.c
+++ b/video/hwdec.c
@@ -107,14 +107,19 @@ char *hwdec_devices_get_names(struct mp_hwdec_devices *devs)
return res;
}
-#if HAVE_D3D_HWACCEL
-extern const struct hwcontext_fns hwcontext_fns_d3d11;
-#endif
-
static const struct hwcontext_fns *const hwcontext_fns[] = {
#if HAVE_D3D_HWACCEL
&hwcontext_fns_d3d11,
#endif
+#if HAVE_D3D9_HWACCEL
+ &hwcontext_fns_dxva2,
+#endif
+#if HAVE_VAAPI
+ &hwcontext_fns_vaapi,
+#endif
+#if HAVE_VDPAU
+ &hwcontext_fns_vdpau,
+#endif
NULL,
};
diff --git a/video/hwdec.h b/video/hwdec.h
index f8a77465f3..69fb86a277 100644
--- a/video/hwdec.h
+++ b/video/hwdec.h
@@ -111,9 +111,14 @@ void *hwdec_devices_load(struct mp_hwdec_devices *devs, enum hwdec_type type);
char *hwdec_devices_get_names(struct mp_hwdec_devices *devs);
struct mp_image;
+struct mpv_global;
+
+struct hwcontext_create_dev_params {
+ bool probing; // if true, don't log errors if unavailable
+};
// Per AV_HWDEVICE_TYPE_* functions, queryable via hwdec_get_hwcontext_fns().
-// For now, all entries are strictly optional.
+// All entries are strictly optional.
struct hwcontext_fns {
int av_hwdevice_type;
// Set any mp_image fields that require hwcontext specific code, such as
@@ -124,10 +129,19 @@ struct hwcontext_fns {
void (*complete_image_params)(struct mp_image *img);
// Fill in special format-specific requirements.
void (*refine_hwframes)(struct AVBufferRef *hw_frames_ctx);
+ // Returns a AVHWDeviceContext*. Used for copy hwdecs.
+ struct AVBufferRef *(*create_dev)(struct mpv_global *global,
+ struct mp_log *log,
+ struct hwcontext_create_dev_params *params);
};
// The parameter is of type enum AVHWDeviceType (as in int to avoid extensive
// recursive includes). May return NULL for unknown device types.
const struct hwcontext_fns *hwdec_get_hwcontext_fns(int av_hwdevice_type);
+extern const struct hwcontext_fns hwcontext_fns_d3d11;
+extern const struct hwcontext_fns hwcontext_fns_dxva2;
+extern const struct hwcontext_fns hwcontext_fns_vaapi;
+extern const struct hwcontext_fns hwcontext_fns_vdpau;
+
#endif
diff --git a/video/vaapi.c b/video/vaapi.c
index 3b1cb9cc41..a6607b4aeb 100644
--- a/video/vaapi.c
+++ b/video/vaapi.c
@@ -97,36 +97,57 @@ static void va_info_callback(const char *msg)
}
#endif
-static void open_lavu_vaapi_device(struct mp_vaapi_ctx *ctx)
+static void free_device_ref(struct AVHWDeviceContext *hwctx)
{
- ctx->av_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
- if (!ctx->av_device_ref)
- return;
+ struct mp_vaapi_ctx *ctx = hwctx->user_opaque;
- AVHWDeviceContext *hwctx = (void *)ctx->av_device_ref->data;
- AVVAAPIDeviceContext *vactx = hwctx->hwctx;
+ if (ctx->display)
+ vaTerminate(ctx->display);
- vactx->display = ctx->display;
+ if (ctx->destroy_native_ctx)
+ ctx->destroy_native_ctx(ctx->native_ctx);
- if (av_hwdevice_ctx_init(ctx->av_device_ref) < 0)
- av_buffer_unref(&ctx->av_device_ref);
+#if !VA_CHECK_VERSION(1, 0, 0)
+ pthread_mutex_lock(&va_log_mutex);
+ for (int n = 0; n < num_va_mpv_clients; n++) {
+ if (va_mpv_clients[n] == ctx) {
+ MP_TARRAY_REMOVE_AT(va_mpv_clients, num_va_mpv_clients, n);
+ break;
+ }
+ }
+ if (num_va_mpv_clients == 0)
+ TA_FREEP(&va_mpv_clients); // avoid triggering leak detectors
+ pthread_mutex_unlock(&va_log_mutex);
+#endif
- ctx->hwctx.av_device_ref = ctx->av_device_ref;
+ talloc_free(ctx);
}
struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog,
bool probing)
{
+ AVBufferRef *avref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
+ if (!avref)
+ return NULL;
+
+ AVHWDeviceContext *hwctx = (void *)avref->data;
+ AVVAAPIDeviceContext *vactx = hwctx->hwctx;
+
struct mp_vaapi_ctx *res = talloc_ptrtype(NULL, res);
*res = (struct mp_vaapi_ctx) {
.log = mp_log_new(res, plog, "/vaapi"),
.display = display,
+ .av_device_ref = avref,
.hwctx = {
.type = HWDEC_VAAPI,
.ctx = res,
+ .av_device_ref = avref,
},
};
+ hwctx->free = free_device_ref;
+ hwctx->user_opaque = res;
+
#if VA_CHECK_VERSION(1, 0, 0)
vaSetErrorCallback(display, va_error_callback, res);
vaSetInfoCallback(display, va_info_callback, res);
@@ -152,9 +173,10 @@ struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog,
}
MP_VERBOSE(res, "Initialized VAAPI: version %d.%d\n", major, minor);
- // For now, some code will still work even if libavutil fails on old crap
- // libva drivers (such as the vdpau wraper). So don't error out on failure.
- open_lavu_vaapi_device(res);
+ vactx->display = res->display;
+
+ if (av_hwdevice_ctx_init(res->av_device_ref) < 0)
+ goto error;
res->hwctx.emulated = va_guess_if_emulated(res);
@@ -169,30 +191,11 @@ error:
// Undo va_initialize, and close the VADisplay.
void va_destroy(struct mp_vaapi_ctx *ctx)
{
- if (ctx) {
- av_buffer_unref(&ctx->av_device_ref);
-
- if (ctx->display)
- vaTerminate(ctx->display);
-
- if (ctx->destroy_native_ctx)
- ctx->destroy_native_ctx(ctx->native_ctx);
-
-#if !VA_CHECK_VERSION(1, 0, 0)
- pthread_mutex_lock(&va_log_mutex);
- for (int n = 0; n < num_va_mpv_clients; n++) {
- if (va_mpv_clients[n] == ctx) {
- MP_TARRAY_REMOVE_AT(va_mpv_clients, num_va_mpv_clients, n);
- break;
- }
- }
- if (num_va_mpv_clients == 0)
- TA_FREEP(&va_mpv_clients); // avoid triggering leak detectors
- pthread_mutex_unlock(&va_log_mutex);
-#endif
+ if (!ctx)
+ return;
- talloc_free(ctx);
- }
+ AVBufferRef *ref = ctx->av_device_ref;
+ av_buffer_unref(&ref); // frees ctx as well
}
VASurfaceID va_surface_id(struct mp_image *mpi)
@@ -298,20 +301,16 @@ static const struct va_native_display *const native_displays[] = {
NULL
};
-static void va_destroy_ctx(struct mp_hwdec_ctx *ctx)
-{
- va_destroy(ctx->ctx);
-}
-
-struct mp_hwdec_ctx *va_create_standalone(struct mpv_global *global,
- struct mp_log *plog, bool probing)
+static struct AVBufferRef *va_create_standalone(struct mpv_global *global,
+ struct mp_log *log, struct hwcontext_create_dev_params *params)
{
for (int n = 0; native_displays[n]; n++) {
VADisplay *display = NULL;
void *native_ctx = NULL;
native_displays[n]->create(&display, &native_ctx);
if (display) {
- struct mp_vaapi_ctx *ctx = va_initialize(display, plog, probing);
+ struct mp_vaapi_ctx *ctx =
+ va_initialize(display, log, params->probing);
if (!ctx) {
vaTerminate(display);
native_displays[n]->destroy(native_ctx);
@@ -319,9 +318,13 @@ struct mp_hwdec_ctx *va_create_standalone(struct mpv_global *global,
}
ctx->native_ctx = native_ctx;
ctx->destroy_native_ctx = native_displays[n]->destroy;
- ctx->hwctx.destroy = va_destroy_ctx;
- return &ctx->hwctx;
+ return ctx->hwctx.av_device_ref;
}
}
return NULL;
}
+
+const struct hwcontext_fns hwcontext_fns_vaapi = {
+ .av_hwdevice_type = AV_HWDEVICE_TYPE_VAAPI,
+ .create_dev = va_create_standalone,
+};
diff --git a/video/vaapi.h b/video/vaapi.h
index 41c9f7c1cb..b2c31d8a74 100644
--- a/video/vaapi.h
+++ b/video/vaapi.h
@@ -49,8 +49,4 @@ VASurfaceID va_surface_id(struct mp_image *mpi);
bool va_guess_if_emulated(struct mp_vaapi_ctx *ctx);
-struct mpv_global;
-struct mp_hwdec_ctx *va_create_standalone(struct mpv_global *global,
- struct mp_log *plog, bool probing);
-
#endif
diff --git a/video/vdpau.c b/video/vdpau.c
index 4aa1a86597..1785702fdb 100644
--- a/video/vdpau.c
+++ b/video/vdpau.c
@@ -337,53 +337,88 @@ static void recheck_preemption(struct mp_hwdec_ctx *hwctx)
mp_vdpau_handle_preemption(ctx, NULL);
}
-static bool open_lavu_vdpau_device(struct mp_vdpau_ctx *ctx)
+static void free_device_ref(struct AVHWDeviceContext *hwctx)
{
- ctx->av_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VDPAU);
- if (!ctx->av_device_ref)
- return false;
+ struct mp_vdpau_ctx *ctx = hwctx->user_opaque;
- AVHWDeviceContext *hwctx = (void *)ctx->av_device_ref->data;
- AVVDPAUDeviceContext *vdctx = hwctx->hwctx;
+ struct vdp_functions *vdp = &ctx->vdp;
+ VdpStatus vdp_st;
- vdctx->device = ctx->vdp_device;
- vdctx->get_proc_address = ctx->get_proc_address;
+ for (int i = 0; i < MAX_VIDEO_SURFACES; i++) {
+ // can't hold references past context lifetime
+ assert(!ctx->video_surfaces[i].in_use);
+ if (ctx->video_surfaces[i].surface != VDP_INVALID_HANDLE) {
+ vdp_st = vdp->video_surface_destroy(ctx->video_surfaces[i].surface);
+ CHECK_VDP_WARNING(ctx, "Error when calling vdp_video_surface_destroy");
+ }
+ if (ctx->video_surfaces[i].osurface != VDP_INVALID_HANDLE) {
+ vdp_st = vdp->output_surface_destroy(ctx->video_surfaces[i].osurface);
+ CHECK_VDP_WARNING(ctx, "Error when calling vdp_output_surface_destroy");
+ }
+ }
+
+ if (ctx->preemption_obj != VDP_INVALID_HANDLE) {
+ vdp_st = vdp->output_surface_destroy(ctx->preemption_obj);
+ CHECK_VDP_WARNING(ctx, "Error when calling vdp_output_surface_destroy");
+ }
- if (av_hwdevice_ctx_init(ctx->av_device_ref) < 0)
- av_buffer_unref(&ctx->av_device_ref);
+ if (vdp->device_destroy && ctx->vdp_device != VDP_INVALID_HANDLE) {
+ vdp_st = vdp->device_destroy(ctx->vdp_device);
+ CHECK_VDP_WARNING(ctx, "Error when calling vdp_device_destroy");
+ }
- ctx->hwctx.av_device_ref = ctx->av_device_ref;
+ if (ctx->close_display)
+ XCloseDisplay(ctx->x11);
- return !!ctx->av_device_ref;
+ pthread_mutex_destroy(&ctx->pool_lock);
+ pthread_mutex_destroy(&ctx->preempt_lock);
+ talloc_free(ctx);
}
struct mp_vdpau_ctx *mp_vdpau_create_device_x11(struct mp_log *log, Display *x11,
bool probing)
{
+ AVBufferRef *avref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VDPAU);
+ if (!avref)
+ return NULL;
+
+ AVHWDeviceContext *hwctx = (void *)avref->data;
+ AVVDPAUDeviceContext *vdctx = hwctx->hwctx;
+
struct mp_vdpau_ctx *ctx = talloc_ptrtype(NULL, ctx);
*ctx = (struct mp_vdpau_ctx) {
.log = log,
.x11 = x11,
.preemption_counter = 1,
+ .av_device_ref = avref,
.hwctx = {
.type = HWDEC_VDPAU,
.ctx = ctx,
.restore_device = recheck_preemption,
+ .av_device_ref = avref,
},
};
mpthread_mutex_init_recursive(&ctx->preempt_lock);
pthread_mutex_init(&ctx->pool_lock, NULL);
+ hwctx->free = free_device_ref;
+ hwctx->user_opaque = ctx;
+
mark_vdpau_objects_uninitialized(ctx);
if (win_x11_init_vdpau_procs(ctx, probing) < 0) {
mp_vdpau_destroy(ctx);
return NULL;
}
- if (!open_lavu_vdpau_device(ctx)) {
+
+ vdctx->device = ctx->vdp_device;
+ vdctx->get_proc_address = ctx->get_proc_address;
+
+ if (av_hwdevice_ctx_init(ctx->av_device_ref) < 0) {
mp_vdpau_destroy(ctx);
return NULL;
}
+
return ctx;
}
@@ -392,37 +427,8 @@ void mp_vdpau_destroy(struct mp_vdpau_ctx *ctx)
if (!ctx)
return;
- struct vdp_functions *vdp = &ctx->vdp;
- VdpStatus vdp_st;
-
- for (int i = 0; i < MAX_VIDEO_SURFACES; i++) {
- // can't hold references past context lifetime
- assert(!ctx->video_surfaces[i].in_use);
- if (ctx->video_surfaces[i].surface != VDP_INVALID_HANDLE) {
- vdp_st = vdp->video_surface_destroy(ctx->video_surfaces[i].surface);
- CHECK_VDP_WARNING(ctx, "Error when calling vdp_video_surface_destroy");
- }
- if (ctx->video_surfaces[i].osurface != VDP_INVALID_HANDLE) {
- vdp_st = vdp->output_surface_destroy(ctx->video_surfaces[i].osurface);
- CHECK_VDP_WARNING(ctx, "Error when calling vdp_output_surface_destroy");
- }
- }
-
- av_buffer_unref(&ctx->av_device_ref);
-
- if (ctx->preemption_obj != VDP_INVALID_HANDLE) {
- vdp_st = vdp->output_surface_destroy(ctx->preemption_obj);
- CHECK_VDP_WARNING(ctx, "Error when calling vdp_output_surface_destroy");
- }
-
- if (vdp->device_destroy && ctx->vdp_device != VDP_INVALID_HANDLE) {
- vdp_st = vdp->device_destroy(ctx->vdp_device);
- CHECK_VDP_WARNING(ctx, "Error when calling vdp_device_destroy");
- }
-
- pthread_mutex_destroy(&ctx->pool_lock);
- pthread_mutex_destroy(&ctx->preempt_lock);
- talloc_free(ctx);
+ AVBufferRef *ref = ctx->av_device_ref;
+ av_buffer_unref(&ref); // frees ctx as well
}
bool mp_vdpau_get_format(int imgfmt, VdpChromaType *out_chroma_type,
@@ -531,16 +537,8 @@ bool mp_vdpau_guess_if_emulated(struct mp_vdpau_ctx *ctx)
return vdp_st == VDP_STATUS_OK && info && strstr(info, "VAAPI");
}
-static void vdpau_destroy_standalone(struct mp_hwdec_ctx *ctx)
-{
- struct mp_vdpau_ctx *vdp = ctx->ctx;
- Display *display = vdp->x11;
- mp_vdpau_destroy(vdp);
- XCloseDisplay(display);
-}
-
-struct mp_hwdec_ctx *vdpau_create_standalone(struct mpv_global *global,
- struct mp_log *plog, bool probing)
+static struct AVBufferRef *vdpau_create_standalone(struct mpv_global *global,
+ struct mp_log *log, struct hwcontext_create_dev_params *params)
{
XInitThreads();
@@ -548,13 +546,20 @@ struct mp_hwdec_ctx *vdpau_create_standalone(struct mpv_global *global,
if (!display)
return NULL;
- struct mp_vdpau_ctx *vdp = mp_vdpau_create_device_x11(plog, display, probing);
+ struct mp_vdpau_ctx *vdp =
+ mp_vdpau_create_device_x11(log, display, params->probing);
if (!vdp) {
XCloseDisplay(display);
return NULL;
}
vdp->hwctx.emulated = mp_vdpau_guess_if_emulated(vdp);
- vdp->hwctx.destroy = vdpau_destroy_standalone;
- return &vdp->hwctx;
+ vdp->close_display = true;
+ mp_warn(log, "idk\n");
+ return vdp->hwctx.av_device_ref;
}
+
+const struct hwcontext_fns hwcontext_fns_vdpau = {
+ .av_hwdevice_type = AV_HWDEVICE_TYPE_VDPAU,
+ .create_dev = vdpau_create_standalone,
+};
diff --git a/video/vdpau.h b/video/vdpau.h
index 1dab72fe84..118db8cbfe 100644
--- a/video/vdpau.h
+++ b/video/vdpau.h
@@ -51,6 +51,7 @@ struct vdp_functions {
struct mp_vdpau_ctx {
struct mp_log *log;
Display *x11;
+ bool close_display;
struct mp_hwdec_ctx hwctx;
struct AVBufferRef *av_device_ref;
@@ -90,10 +91,6 @@ struct mp_vdpau_ctx *mp_vdpau_create_device_x11(struct mp_log *log, Display *x11
bool probing);
void mp_vdpau_destroy(struct mp_vdpau_ctx *ctx);
-struct mpv_global;
-struct mp_hwdec_ctx *vdpau_create_standalone(struct mpv_global *global,
- struct mp_log *plog, bool probing);
-
int mp_vdpau_handle_preemption(struct mp_vdpau_ctx *ctx, uint64_t *counter);
struct mp_image *mp_vdpau_get_video_surface(struct mp_vdpau_ctx *ctx,