diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/decode/d3d.c | 36 | ||||
-rw-r--r-- | video/decode/hw_d3d11va.c | 47 | ||||
-rw-r--r-- | video/decode/hw_dxva2.c | 36 | ||||
-rw-r--r-- | video/decode/lavc.h | 4 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 35 | ||||
-rw-r--r-- | video/hwdec.c | 13 | ||||
-rw-r--r-- | video/hwdec.h | 16 | ||||
-rw-r--r-- | video/vaapi.c | 95 | ||||
-rw-r--r-- | video/vaapi.h | 4 | ||||
-rw-r--r-- | video/vdpau.c | 119 | ||||
-rw-r--r-- | video/vdpau.h | 5 |
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, ¶ms); + 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, |