summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-12-01 08:01:08 +0100
committerwm4 <wm4@nowhere>2017-12-01 08:05:16 +0100
commita0d9e15342ad48f51841d4fbfe3ae47e10e45592 (patch)
treee08465a5e54136e55ab2a35b2382fb9d8d06d634
parentafd5f3227ec38fea70bf7abfcd107a9493aa21fc (diff)
downloadmpv-a0d9e15342ad48f51841d4fbfe3ae47e10e45592.tar.bz2
mpv-a0d9e15342ad48f51841d4fbfe3ae47e10e45592.tar.xz
video: refactor hw device creation for hwdec copy modes
Lots of shit code for nothing. We probably could just use libavutil's code for all of this. But for now go with this, since it tends to prevent stupid terminal messages during probing (libavutil has no mechanism to selectively suppress errors specifically during probing). Ignores the "emulated" API flag (for avoiding vaapi/vdpau wrappers), but it doesn't matter that much for -copy anyway.
-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,