summaryrefslogtreecommitdiffstats
path: root/video
Commit message (Collapse)AuthorAgeFilesLines
* vo_sdl: Only create the SDL window onceCameron Cawley2019-09-211-54/+23
|
* context_drm_egl: Use eglGetPlatformDisplayEXT if availablememeka2019-09-201-1/+20
| | | | | | | | Check if eglGetPlatformDisplayEXT is available and try to use it to obtain the display connection. Fall back to eglGetDisplay if eglGetPlatformDisplayEXT is not available or failing. From PR #5992
* client API, vo_libmpv: document random deadlock problemswm42019-09-201-0/+16
| | | | | | | I guess trying to make DR work on libmpv was a mistake. I never observed such a deadlock, but it's looks like it's theoretically possible.
* vo_libmpv: fix some more uninit issueswm42019-09-201-24/+35
| | | | | | | | | | | | | | | | | | | | | | This is mostly for the case when mpv_render_context_free() is called while video is going on. This is supposed to gracefully stop video and deinitialize everything properly. (I feel like it would put too much on the API user to require that video is stopped before calling this function. Whether video is running or not is a fairly highlevel thing, and the API user could not do it in a race-free way.) One problem was that unit() accessed ctx after ctx->in_use was set to false. The update(ctx) call was basically a racy use-after-free. It needed that call to wake up the mpv_render_context_free() loop that waited for VO uninit. Fix this by triggering the wakeup inside the lock, and then doing "barrier" locking in mpv_render_context_free(). Another problem was that the wait loop didn't really wait properly. IT seems the had_kill_update field was a botched attempt to do that. It's indeed quite hairy to do that with update(). Instead make use of the dispatch queue (infinite timeout, using mp_dispatch_interrupt()), which handles the problem of having to wait both for dispatch queue updates and VO uninit at the same time.
* vo_libmpv: always create ctx->dispatchwm42019-09-201-19/+12
| | | | | | | | Preparation for the next commit. Until now, it was only needed if DR was involved. One reason for not always creating it was that you normally must not use it if advanced_control is not enabled. This is why e.g. VOCTRL_SCREENSHOT now checks for that variable; it still can't use ctx->dispatch if the render API user did not enable it.
* render api: fix use-after-freewnoun2019-09-201-12/+2
| | | | | | | | render api needs to wait for vo to be destroyed before frees the context. The purpose of kill_cb is to wake up render api after vo is destroyed, but uninit did that before kill_cb, so kill_cb tries using the freed memory. Remove kill_cb to fix the issue as uninit is able to do the work.
* rpi: Update for modern systemsCameron Cawley2019-09-203-6/+6
|
* vo: remove unused equalizer control remainswm42019-09-201-14/+1
| | | | | | | | | | Equalizer control was redone in 03cf150ff3516789d5812 (over 2 years ago). Ever since, the equalizer control structs and the GET voctrl have been unused. Only the SET voctrl is still used as notification mechanism (actually a bad hack to avoid some further option change handling complexity). Remove the unused parts.
* oml_sync: fix typo in commentwm42019-09-201-2/+2
| | | | I think... Also reword another part of the text.
* vf_fingerprint: use aligned_alloc instead of posix_memalignwm42019-09-191-2/+2
| | | | | | | | | | | I was assuming posix_memalign was the most portable function to use, but MinGW does not provide it for some reason. Switch to C11 aligned_alloc() which someone suggested was provided by MinGW (but actually isn't, someone probably confused it with the incompatible _aligned_malloc), and add a configure check. Even though it turned out that MinGW doesn't provide it, the function is slightly more elegant than posix_memalign(), so stay with it.
* video: add vf_fingerprint and a skip-logo scriptwm42019-09-191-0/+293
| | | | | | | | | | | | | | | | | | | | | | | | | skip-logo.lua is just what I wanted to have. Explanations are on the top of that file. As usual, all documentation threatens to remove this stuff all the time, since this stuff is just for me, and unlike a normal user I can afford the luxuary of hacking the shit directly into the player. vf_fingerprint is needed to support this script. It needs to scale down video frames as part of its operation. For that, it uses zimg. zimg is much faster than libswscale and generates more correct output. (The filter includes a runtime fallback, but it doesn't even work because libswscale fucks up and can't do YUV->Gray with range adjustment.) Note on the algorithm: seems almost too simple, but was suggested to me. It seems to be pretty effective, although long time experience with false positives is missing. At first I wanted to use dHash [1][2], which is also pretty simple and effective, but might actually be worse than the implemented mechanism. dHash has the advantage that the fingerprint is smaller. But exact matching is too unreliable, and you'd still need to determine the number of different bits for fuzzier comparison. So there wasn't really a reason to use it. [1] https://pypi.org/project/dhash/ [2] http://www.hackerfactor.com/blog/index.php?/archives/529-Kind-of-Like-That.html
* video: generally try to align image data on 64 byteswm42019-09-195-4/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Generally, using x86 SIMD efficiently (or crash-free) requires aligning all data on boundaries of 16, 32, or 64 (depending on instruction set used). 64 bytes is needed or AVX-512, 32 for old AVX, 16 for SSE. Both FFmpeg and zimg usually require aligned data for this reason. FFmpeg is very unclear about alignment. Yes, it requires you to align data pointers and strides. No, it doesn't tell you how much, except sometimes (libavcodec has a legacy-looking avcodec_align_dimensions2() API function, that requires a heavy-weight AVCodecContext as argument). Sometimes, FFmpeg will take a shit on YOUR and ITS OWN alignment. For example, vf_crop will randomly reduce alignment of data pointers, depending on the crop parameters. On the other hand, some libavfilter filters or libavcodec encoders may randomly crash if they get the wrong alignment. I have no idea how this thing works at all. FFmpeg usually doesn't seem to signal alignment internal anywhere, and usually leaves it to av_malloc() etc. to allocate with proper alignment. libavutil/mem.c currently has a ALIGN define, which is set to 64 if FFmpeg is built with AVX-512 support, or as low as 16 if built without any AVX support. The really funny thing is that a normal FFmpeg build will e.g. align tiny string allocations to 64 bytes, even if the machine does not support AVX at all. For zimg use (in a later commit), we also want guaranteed alignment. Modern x86 should actually not be much slower at unaligned accesses, but that doesn't help. zimg's dumb intrinsic code apparently randomly chooses between aligned or unaligned accesses (depending on compiler, I guess), and on some CPUs these can even cause crashes. So just treat the requirement to align as a fact of life. All this means that we should probably make sure our own allocations are 64 bit aligned. This still doesn't guarantee alignment in all cases, but it's slightly better than before. This also makes me wonder whether we should always override libavcodec's buffer pool, just so we have a guaranteed alignment. Currently, we only do that if --vd-lavc-dr is used (and if that actually works). On the other hand, it always uses DR on my machine, so who cares.
* vo: fix missed option updates under rare circumstanceswm42019-09-191-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Dear diary, today I fixed a shitty bug that was all my fault because I made a horrible mess. (Except it was a horrible mess before I even touched this shit, but let's not blame others.) Sometimes, updates to VO option that control video sizing (like panscan) didn't update the screen correctly. They were delayed until the next option change or so. It turns out that if the option update happens at the "same" time as a VOCTRL, update_opts() doesn't actually notify the vo_driver of the change. This in turn happened because run_control() called m_config_cache_update(). The latter function returns true if the options changed since the last call, and update_opts() also calls it (on the same config cache) for the same purpose. The update_opts() call, which is triggered by a third mechanism, comes later, but the cache update call will return false (as it should). Basically, given the config API, you can't act differently on multiple update calls and expect it to work. The skipped handling in update_opts() meant that the notification required to apply the changed option wasn't run. Fix this by simply calling update_opts() directly instead. Now there's only 1 m_config_cache_update() call on this specific instance. Fix the call in run_reconfig() too, so the previous sentence isn't a lie (but it probably doesn't make a difference in practice due to certain details). I'm not sure how I even ran into this sort-of race condition. The VOCTRL that messed up the option update was VOCTRL_UPDATE_PLAYBACK_STATE, which happens semi-regularly. Why this config cache shit and all the other shit? Rediscovering this crap wasn't pleasant. It's a bunch of hacks that became necessary when the ancient MPlayer architecture made it hard to move the VO to a separate thread. All the VO code typically accesses vo->opts (whose fields all used to be global variables in MPlayer). The frontend changes these on user input. Putting locking around all the options would be a nightmare, and keeping a copy of the options in the thread was much simpler. You need a way to propagate option changes, notify the thread, and update the local copy too. And the result of these thoughts was the config cache mechanism. In this specific case, the relevant cache update call in update_opts() triggers a VOCTRL_SET_PANSCAN to the VO driver, which isn't related to its former function anymore. Instead, it causes the VO driver to update the video sizing/placing options, which the generic VO code can't do. (Mostly because the VO driver includes the windowing stuff and is responsible for resizing etc. itself.) VOCTRLs sent by the frontend are even worse. MPlayer had no real runtime option change mechanism. Some options were vaguely duplicated by properties, so you could effectively change those options at runtime. Each of these options had its own VOCTRL, which still exist today, e.g. VOCTRL_FULLSCREEN, or VOCTRL_ONTOP. I tried to make all options runtime changeable, and to unify properties with options. But I couldn't be bothered with updating all VO drivers to listen to option changes directly, because that would be pretty tedious. So the property code is still all there and sends the old VOCTRLs. But of course you need to sync up the options, which is why the run_control() code did that. (Unrelated: VO_EVENT_FULLSCREEN_STATE is the worst shithack of them all. Currently, only the frontend can actually write to options (for awful reasons), so if the fullscreen state changes due to outside interaction, the VO driver can't update the corresponding option fields. So the VO notifies the frontend with said VO_EVENT_, and the frontend then sends VOCTRL_GET_FULLSCREEN, and updates the global copy of the option with the value returned by that. I still like to think the situation is not that bad considering the monstrous effort of converting single-threaded code that had hundreds of options in global variables to multi-threaded code with no global variables at all.)
* win_state: silence a valgrind warningwm42019-09-191-1/+1
| | | | | | | m_geometry_apply() will read and modify the dummy variable. It's not actually used for anything, but valgrind will still warn against uninitialized data. I'm not sure whether this was UB, but in any case it's annoying when running valgrind.
* vd_lavc: put vaapi before vdpau in autoprobe orderwm42019-09-191-2/+2
| | | | | | | | | --hwdec=auto-copy was preferring vdpau over vaapi. In the HEVC 10 bit case, this also led to hardware decoding not being enabled. (Probably because the probing can't start over after enabling hw decoding fails at runtime, or something like that.) Possible that this subtly breaks on some setups. You can't always win.
* vo_gpu: hwdec_vaegl: silence confusing message during probingwm42019-09-191-2/+47
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | During probing on a system with AMD GPU, mpv used to output the following messages if hardware decoding was enabled: [ffmpeg] AVHWFramesContext: Failed to create surface: 2 (resource allocation failed). [ffmpeg] AVHWFramesContext: Unable to allocate a surface from internal buffer pool. This commit removed the message, with hopefully no other side effects. Long explanations follow, better don't read them, it's just tedious drivel about the details. People should learn to write concise commit messages, not drone on and on endlessly all while they have no fucking point. The code probes supported hardware pixel format, and checks whether they can be mapped as textures. av_hwdevice_get_hwframe_constraints() returns a list of hardware pixel formats in the valid_sw_formats field (the "sw" means software, but they're still hardware pixel formats, makes sense). This contained the format yuv420p, even though this is not a valid hardware format. Trying to create a surface of this type results in VA surface creation failure, upon which FFmpeg prints the error messages above. We'd be fine with this, except FFmpeg has a global log callback, and there's no way to suppress these messages without creating other issues. It turns out that FFmpeg's vaapi implementation returns all formats from vaQueryImageFormats() if no "hwconfig" is provided. This list includes yuv420p, which is probably supported for surface upload/download, but not as native format. Following FFmpeg's logic, it should not appear in the valid_sw_formats list, because formats for transfers are returned by another roundabout API. Idiotically, there doesn't seem to be any vaapi call that determines whether a format is a valid surface format. All mechanisms to do this are bound to a VAConfigID (= video codec or video processor), all while the actual surface creation API strangely does not take a VAConfigID (a big WTF). Also, calling the vaCreateSurfaces() API ourselves for probing is out of the question, because that functions is utterly and idiotically complex. Look at the FFmpeg code and how much effort it requires to setup a complete set of attributes - we can't duplicate this. So the only way left to do this is the most idiotic and tedious way: enumerating all VAProfile (and VAEntrypoints) to create all possible VAConfigIDs. Each of the VAConfigIDs is associated with a list of formats, which FFmpeg can return (by passing the ID along with the "hwconfig"), and which is probed separately. Note that VAConfigID actually refers to a dynamic instance of something, and creating a VAConfigID takes not only the VAProfile and the VAEntrypoint, but also an arbitrary attribute array. In theory, this means our attempt to get to know all possible configurations cannot work, but in practice this attribute array seems to be pointless for decoding and video processing, and FFmpeg doesn't use it (though the encoding path does use it). This probably just makes it _barely_ OK to do it this way. Could we discard all this probing shit, and somehow do it another way? Probably not. The EGL API for mapping surfaces doesn't even seem to provide a way to enumerate supported formats, we may not even know whether DRM/dmabuf interop is actually supported (AFAIR the EGL extensions are present even if they don't work), nor do we know whether the VAAPI driver supports this interop (not sure). So actually trying is the only way. Further, mpv initializes the decoder on a another thread, where you can't just access OpenGL state. This suckage is mostly to be blamed on OpenGL itself and its crazy thread boundedness. In theory, this could be done anyway (see how software decoding "direct rendering" tries to get around this). But to make it worse, the decoder never cares about the list of supported formats determined by this code; instead, f_autoconvert.c tries to deal with it and insert a video processor (well, good luck with this crap, I bet it doesn't even work). So this whole endeavor might be pointless, other than the fact that failed probing can disable use of vaapi (which is correct and necessary). But if you have a shovel, you don't use it to smash the flat end on the heap of shit that's piled up before you, or do you? While this method probably works, it's still orgasmically tedious. It was tedious before: we had to create a real surface, create a GL texture, map the surface with it, then destroy everything again. But the added code is tedious on its own. Highlights include the need to malloc a FFmpeg struct just to pass a single damn integer, the need to enumerate "entrypoints" for each VA profile, even though all profiles have exactly 1 entrypoint, and the kind of obnoxious way how vaapi requires you to preallocate arrays for returned things, even they could for example reasonably be returned as immutable arrays or have some other simpler API. The main grand fuckup is of course that vaapi requires a VAConfigID to query surface properties, but not for creating surfaces. This awkwardness even affected the FFmpeg API design, which has a "hwconfig" concept that is only used by vaapi (vaapi is only 1 out of 10 hardware decoding APIs supported by the FFmpeg hwcontext stuff). Maybe I'm just missing something. It's as if vaapi required setting radioactive shit on fire. Look how clean the native D3D11 code is instead. (Even the ANGLE code manages to avoid being this fucked up. Or the VDPAU code, despite supporting multiple mapping methods.) Another only barely related change is that the valid_sw_formats field can be NULL, and the API explicitly documents this. Technically, the mpv code was buggy for not checking this, although until now the FFmpeg implementation so far could not return it when we still passed NULL for the hwconfig parameter.
* vo_gpu: hwdec_vaegl: refactor format probingwm42019-09-191-40/+64
| | | | | | | | | | | No functional changes, just preparation for the next commit. Split the probing into multiple functions. Prepare for the yet unused possibility to pass AVVAAPIHWConfig to probing. try_format_pixfmt() now assumes it can be called multiple times with the same format, so it filters the format. The format probing is now something like O(n^2) for n formats, but n will most likely remain something under 50 or so.
* vf_vapourynth: remove Lua backendwm42019-09-191-241/+1
| | | | | | | | | | | | | | | I once created this because someone wanted to use vapoursynth without the Python dependency. No idea if anyone ever actually used it. It's sort of icky (it calls itself "lazy" to preempt complaints about how much it sucks), and complicates the build process. Kill it. It seems much more promising to have something like this: https://github.com/vapoursynth/vapoursynth/issues/386 This would either solve the build distribution problem by relaxing the Python dependency, and/or allow a Lua backend to be included without pain.
* vo_gpu: remove vdpau/GLX backendwm42019-09-192-421/+0
| | | | | | | Useless garbage. This was once added to test whether vdpau presentation feedback could be used. Results were always unsatisfactory, and now vdpau is dead.
* vo_gpu: remove mali-fbdevwm42019-09-192-162/+0
| | | | | Useless at this point, I don't even know if it still works, or how to test it.
* aspect: add video margin optionswm42019-09-191-5/+43
| | | | | | | | | | | | | | | Semantics a bit questionable. This is done for the OSC (next commit), and a comment added the manpage explicitly states this. Meaning this is probably garbage and needs to revisit when the OSC changes and/or someone wants to use this margin feature for something else. Not sure about the subtitle thing. It's imaginable that someone uses these options to create empty borders for subtitles on the bottom, so subtitles should be located there. On the other hand, this gives a rather unpolished user experience when using the (later added) OSC feature to not overlap with the video. There's not much of a point if the OSC still overlaps the video. However, I'm too lazy to think about this, so it stays like it is.
* aspect: fix some UB problems in corner caseswm42019-09-191-6/+6
| | | | | | | | | | | --video-margin-ratio-left=0.2 --video-margin-ratio-right=0.9 (added in the the next commit) will set f_w to inf, resulting in some garbage being propagated. Later, the OSD margins are computed from values before various sanity clamping is applied, which makes libass suffer from bullshit values. I'm very sure it's OK and more correct to compute the OSD margins using the later values, but I'm not sure about that.
* vd_lavc: add --hwdec-extra-frames optionwm42019-09-191-7/+8
| | | | Surprised this didn't exist before.
* Implement backwards playbackwm42019-09-192-0/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | See manpage additions. This is a huge hack. You can bet there are shit tons of bugs. It's literally forcing square pegs into round holes. Hopefully, the manpage wall of text makes it clear enough that the whole shit can easily crash and burn. (Although it shouldn't literally crash. That would be a bug. It possibly _could_ start a fire by entering some sort of endless loop, not a literal one, just something where it tries to do work without making progress.) (Some obvious bugs I simply ignored for this initial version, but there's a number of potential bugs I can't even imagine. Normal playback should remain completely unaffected, though.) How this works is also described in the manpage. Basically, we demux in reverse, then we decode in reverse, then we render in reverse. The decoding part is the simplest: just reorder the decoder output. This weirdly integrates with the timeline/ordered chapter code, which also has special requirements on feeding the packets to the decoder in a non-straightforward way (it doesn't conflict, although a bugmessmass breaks correct slicing of segments, so EDL/ordered chapter playback is broken in backward direction). Backward demuxing is pretty involved. In theory, it could be much easier: simply iterating the usual demuxer output backward. But this just doesn't fit into our code, so there's a cthulhu nightmare of shit. To be specific, each stream (audio, video) is reversed separately. At least this means we can do backward playback within cached content (for example, you could play backwards in a live stream; on that note, it disables prefetching, which would lead to losing new live video, but this could be avoided). The fuckmess also meant that I didn't bother trying to support subtitles. Subtitles are a problem because they're "sparse" streams. They need to be "passively" demuxed: you don't try to read a subtitle packet, you demux audio and video, and then look whether there was a subtitle packet. This means to get subtitles for a time range, you need to know that you demuxed video and audio over this range, which becomes pretty messy when you demux audio and video backwards separately. Backward display is the most weird (and potentially buggy) part. To avoid that we need to touch a LOT of timing code, we negate all timestamps. The basic idea is that due to the navigation, all comparisons and subtractions of timestamps keep working, and you don't need to touch every single of them to "reverse" them. E.g.: bool before = pts_a < pts_b; would need to be: bool before = forward ? pts_a < pts_b : pts_a > pts_b; or: bool before = pts_a * dir < pts_b * dir; or if you, as it's implemented now, just do this after decoding: pts_a *= dir; pts_b *= dir; and then in the normal timing/renderer code: bool before = pts_a < pts_b; Consequently, we don't need many changes in the latter code. But some assumptions inhererently true for forward playback may have been broken anyway. What is mainly needed is fixing places where values are passed between positive and negative "domains". For example, seeking and timestamp user display always uses positive timestamps. The main mess is that it's not obvious which domain a given variable should or does use. Well, in my tests with a single file, it suddenly started to work when I did this. I'm honestly surprised that it did, and that I didn't have to change a single line in the timing code past decoder (just something minor to make external/cached text subtitles display). I committed it immediately while avoiding thinking about it. But there really likely are subtle problems of all sorts. As far as I'm aware, gstreamer also supports backward playback. When I looked at this years ago, I couldn't find a way to actually try this, and I didn't revisit it now. Back then I also read talk slides from the person who implemented it, and I'm not sure if and which ideas I might have taken from it. It's possible that the timestamp reversal is inspired by it, but I didn't check. (I think it claimed that it could avoid large changes by changing a sign?) VapourSynth has some sort of reverse function, which provides a backward view on a video. The function itself is trivial to implement, as VapourSynth aims to provide random access to video by frame numbers (so you just request decreasing frame numbers). From what I remember, it wasn't exactly fluid, but it worked. It's implemented by creating an index, and seeking to the target on demand, and a bunch of caching. mpv could use it, but it would either require using VapourSynth as demuxer and decoder for everything, or replacing the current file every time something is supposed to be played backwards. FFmpeg's libavfilter has reversal filters for audio and video. These require buffering the entire media data of the file, and don't really fit into mpv's architecture. It could be used by playing a libavfilter graph that also demuxes, but that's like VapourSynth but worse.
* wayland: fix wl_proxy leakdudemanguy2019-09-191-0/+3
| | | | | | | | | | | | | | | | | | This one is probably not terribly obvious from just the valgrind log, but a wayland dev explained it to me just a second ago. Whenever mpv sends events to the screen with wl_display_dispatch, wayland internally allocates memory to a struct wl_proxy object if a new id is found. Quite a few more things happen to that proxy object, but eventually mpv stores the data on the client-side in a wrapper type of struct (struct wl_data_offer). mpv's data_device_listener keeps track of those proxies and frees the memory when appropriate. Of course, mpv is constantly sending events to the screen and does so until the user quits the player. What happens here is that one final wl_display_dispatch is called right before the user quits the player and before mpv's data_device_listener can handle that object. So the result is that you always have one extra dangling proxy that doesn't get properly freed. The solution is to just simply call wl_data_offer_destroy before closing the wl_display to free that final dangling wl_proxy.
* drm: fix libmpv ABI breakage introduced in ↵Anton Kindestam2019-09-184-13/+13
| | | | | | | | | | | | | | | 351c083487050c88adb0e3d60f2174850f869018 Extending the client-allocated mpv_opengl_drm_params struct constituted a break of ABI that could cause UB. Create a clean break by deprecating "drm_params" and related structs and enum values, and replacing it with "drm_params_v2". Also fix some comments and code that wrongly assumed that open could return any other negative number than -1 for failure. This commit updates the libmpv version to 1.104
* vo_gpu: hwdec_vaapi: Refactor Vulkan and OpenGL interops for VAAPIPhilip Langdale2019-09-155-326/+471
| | | | | | Like hwdec_cuda, you get a big #ifdef mess if you try and keep the OpenGL and Vulkan interops in the same file. So, I've refactored them into separate files in a similar way.
* vo_gpu: hwdec_cuda: Improve interop selection mechanismPhilip Langdale2019-09-154-15/+20
| | | | | | This change updates the interop selection to match what I did for VAAPI, by iterating through an array of init functions until one of them works.
* vo_gpu: x11: remove special vdpau probing, use EGL by defaultwm42019-09-152-29/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Originally, vo_gpu/vo_opengl considered the case of Nvidia proprietary drivers, which required vdpau/GLX, and Intel open source drivers, which require vaapi/EGL. Since window creation and GPU context creation are inseparable in mpv's internal API, it had to pick the correct API very early, or hardware decoding wouldn't work. "x11probe" was introduced for this reason. It created a GLX context (without showing the window yet), and checked whether vdpau was available. If yes, it used GLX, if not, it continued probing x11/EGL. (Obviously it couldn't always fail on GLX without vdpau, which is why it was a separate "probe" backend.) Years passed, and now the situation is different. Vdpau is dead. Nvidia drivers and libavcodec now provide CUDA interop, which requires EGL, and fixes some of the vdpau problems. AMD drivers now provide vaapi, which generally works better than vdpau. Intel didn't change. In particular, vaapi provides working HEVC Main10 support. In theory, it should work on vdpau too, with quality reduction (no 10 bit surfaces), but I couldn't get it to work. So always prefer EGL. And suddenly hardware decoding works. This is actually rather important, because HEVC is unfortunately on the rise, despite shitty encoders and unoptimized decoders. The latter may mean that hardware decoding works better than libavcodec. This should have been done a long, long time ago.
* vf_vavpp: disable this filterwm42019-09-151-0/+9</