summaryrefslogtreecommitdiffstats
path: root/video/decode/vd_lavc.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-05-19 15:24:38 +0200
committerwm4 <wm4@nowhere>2017-05-19 15:24:38 +0200
commit7aa070e1cb3fcb1b1c8b91f3b324c45dd481368f (patch)
tree3a54dc9b7811cd48207a39d3f2eab3051fdc7a68 /video/decode/vd_lavc.c
parent3a7b4df4bfd2d75140b0ebb89af9411f2902be04 (diff)
downloadmpv-7aa070e1cb3fcb1b1c8b91f3b324c45dd481368f.tar.bz2
mpv-7aa070e1cb3fcb1b1c8b91f3b324c45dd481368f.tar.xz
vdpau: crappy hack to allow initializing hw decoding after preemption
If vo_opengl is used, and vo_opengl already created the vdpau interop (for whatever reasons), and then preemption happens, and then you try to enable hw decoding, it failed. The reason was that preemption recovery is not run at any point before libavcodec accesses the vdpau device. The actual impact was that with libmpv + opengl-cb use, hardware decoding was permanently broken after display mode switching (something that caused the display to get preempted at least with older drivers). With mpv CLI, you can for example enable hw decoding during playback, then disable it, VT switch to console, switch back to X, and try to enable hw decoding again. This is mostly because libav* does not deal with preemption, and NVIDIA driver preemption behavior being horrible garbage. In addition to being misdesigned API, the preemption callback is not called before you try to access vdpau API, and then only with _some_ accesses. In summary, the preemption callback was never called, neither before nor after libavcodec tried to init the decoder. So we have to get mp_vdpau_handle_preemption() called before libavcodec accesses it. This in turn will do a dummy API access which usually triggers the preemption callback immediately (with NVIDIA's drivers). In addition, we have to update the AVHWDeviceContext's device. In theory it could change (in practice it usually seems to use handle "0"). Creating a new device would cause chaos, as we don't have a concept of switching the device context on the fly. So we simply update it directly. I'm fairly sure this violates the libav* API, but it's the best we can do.
Diffstat (limited to 'video/decode/vd_lavc.c')
-rw-r--r--video/decode/vd_lavc.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index fe4409968a..9c1a2a0317 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -603,6 +603,8 @@ 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;
+ if (ctx->hwdec_dev->restore_device)
+ ctx->hwdec_dev->restore_device(ctx->hwdec_dev);
if (!ctx->hwdec->set_hwframes) {
#if HAVE_VDPAU_HWACCEL
avctx->hw_device_ctx = av_buffer_ref(ctx->hwdec_dev->av_device_ref);