diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index fd4bf59092..d51e834ce2 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -125,8 +125,6 @@ const struct m_sub_options vd_lavc_conf = { }, }; -extern const struct vd_lavc_hwdec mp_vd_lavc_vdpau; -extern const struct vd_lavc_hwdec mp_vd_lavc_vdpau_copy; extern const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox; extern const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox_copy; extern const struct vd_lavc_hwdec mp_vd_lavc_dxva2; @@ -205,12 +203,43 @@ extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy; #endif #endif +#if HAVE_VDPAU_HWACCEL +#if HAVE_VDPAU_HWACCEL_NEW +const struct vd_lavc_hwdec mp_vd_lavc_vdpau = { + .type = HWDEC_VDPAU, + .image_format = IMGFMT_VDPAU, + .generic_hwaccel = true, + .pixfmt_map = (const enum AVPixelFormat[][2]) { + {AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P}, + {AV_PIX_FMT_NONE} + }, +}; + +#include "video/vdpau.h" + +const struct vd_lavc_hwdec mp_vd_lavc_vdpau_copy = { + .type = HWDEC_VDPAU_COPY, + .copying = true, + .image_format = IMGFMT_VDPAU, + .generic_hwaccel = true, + .create_dev = vdpau_create_standalone, + .pixfmt_map = (const enum AVPixelFormat[][2]) { + {AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P}, + {AV_PIX_FMT_NONE} + }, +}; +#else +extern const struct vd_lavc_hwdec mp_vd_lavc_vdpau; +extern const struct vd_lavc_hwdec mp_vd_lavc_vdpau_copy; +#endif +#endif + static const struct vd_lavc_hwdec *const hwdec_list[] = { #if HAVE_RPI &mp_vd_lavc_rpi, &mp_vd_lavc_rpi_copy, #endif -#if HAVE_VDPAU_HWACCEL +#if HAVE_VDPAU_HWACCEL_OLD || HAVE_VDPAU_HWACCEL_NEW &mp_vd_lavc_vdpau, &mp_vd_lavc_vdpau_copy, #endif @@ -555,6 +584,9 @@ static void init_avctx(struct dec_video *vd, const char *decoder, if (ctx->hwdec) { avctx->thread_count = 1; +#if HAVE_VDPAU_HWACCEL_NEW + avctx->hwaccel_flags |= AV_HWACCEL_FLAG_IGNORE_LEVEL; +#endif if (ctx->hwdec->image_format) avctx->get_format = get_format_hwdec; if (ctx->hwdec->allocate_image) @@ -797,6 +829,12 @@ static int init_generic_hwaccel(struct dec_video *vd) ctx->hwdec_fmt = hwdec->image_format; + if (hwdec->image_format == IMGFMT_VDPAU && + ctx->avctx->codec_id == AV_CODEC_ID_HEVC) + { + MP_WARN(ctx, "HEVC video output may be broken due to nVidia bugs.\n"); + } + return hwdec_setup_hw_frames_ctx(ctx, ctx->hwdec_dev->av_device_ref, av_sw_format, pool_size); } diff --git a/video/vdpau.c b/video/vdpau.c index f4c85a0bab..8895053249 100644 --- a/video/vdpau.c +++ b/video/vdpau.c @@ -605,3 +605,31 @@ bool mp_vdpau_guess_if_emulated(struct mp_vdpau_ctx *ctx) CHECK_VDP_WARNING(ctx, "Error when calling vdp_get_information_string"); 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) +{ + XInitThreads(); + + Display *display = XOpenDisplay(NULL); + if (!display) + return NULL; + + struct mp_vdpau_ctx *vdp = mp_vdpau_create_device_x11(plog, display, 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; +} diff --git a/video/vdpau.h b/video/vdpau.h index bffe901373..b320fa525a 100644 --- a/video/vdpau.h +++ b/video/vdpau.h @@ -88,6 +88,10 @@ 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, diff --git a/wscript b/wscript index 318228cca2..098f53b131 100644 --- a/wscript +++ b/wscript @@ -832,10 +832,27 @@ hwaccel_features = [ 'desc': 'Videotoolbox with OpenGL', 'deps': [ 'gl-cocoa', 'videotoolbox-hwaccel' ], 'func': check_true - } , { + }, { 'name': '--vdpau-hwaccel', 'desc': 'libavcodec VDPAU hwaccel', 'deps': [ 'vdpau' ], + 'func': check_true, + }, { + 'name': '--vdpau-hwaccel-new', + 'desc': 'libavcodec VDPAU hwaccel (new)', + 'deps': [ 'vdpau-hwaccel' ], + 'func': check_statement('libavcodec/version.h', + 'int x[(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 1) && ' + ' LIBAVCODEC_VERSION_MICRO < 100) ||' + ' (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 85, 101) && ' + ' LIBAVCODEC_VERSION_MICRO >= 100)' + ' ? 1 : -1]', + use='libav'), + }, { + 'name': '--vdpau-hwaccel-old', + 'desc': 'libavcodec VDPAU hwaccel (old)', + 'deps': [ 'vdpau' ], + 'deps_neg': [ 'vdpau-hwaccel-new' ], 'func': check_statement('libavcodec/vdpau.h', 'av_vdpau_bind_context(0,0,0,AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH)', use='libav'), diff --git a/wscript_build.py b/wscript_build.py index 4934bd64f7..6014367115 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -310,7 +310,7 @@ def build(ctx): ( "video/decode/hw_dxva2.c", "d3d-hwaccel" ), ( "video/decode/hw_d3d11va.c", "d3d-hwaccel" ), ( "video/decode/hw_vaapi_old.c", "vaapi-hwaccel-old" ), - ( "video/decode/hw_vdpau.c", "vdpau-hwaccel" ), + ( "video/decode/hw_vdpau.c", "vdpau-hwaccel-old" ), ( "video/decode/hw_videotoolbox.c", "videotoolbox-hwaccel" ), ( "video/decode/vd_lavc.c" ), ( "video/filter/refqueue.c" ),