mpv icon indicating copy to clipboard operation
mpv copied to clipboard

Trying to use the GPU on a headless server to decode and encode

Open twilson90 opened this issue 1 year ago • 13 comments
trafficstars

I have a server with a Intel® Xeon® Processor E3-1245 v5, which has an onboard GPU, Intel® HD Graphics P530 with QuickSync.: https://www.intel.com/content/www/us/en/products/sku/88173/intel-xeon-processor-e31245-v5-8m-cache-3-50-ghz/specifications.html I'd like to use the GPU when possible to decode and/or encode video using MPV. I've tried running some tests using the latest FFMPEG and after much trying I managed to decode some video with the GPU but it required a very precise set of parameters. What parameters are necessary to use a GPU with QuickSync for decoding and encoding in MPV, and do I need to build it with any particular libraries enabled to get it working?

twilson90 avatar Jan 28 '24 14:01 twilson90

On a Linux system, you're unlikely wanting to go through the QuickSync layer but instead want to go through va-api instead, which pokes precisely the same hardware but through a more commonly used path.

You can specify to use hardware decoding through vaapi with --hwdec=vaapi. You can manually specify a device with --vaapi-device, which defaults to /dev/dri/renderD128. If this is not the right one for you, you can select one of the other devices in that subdirectory.

As for encoding with vaapi, --ovc=<codecdname>_vaapi might suffice, see --ovc=help for a list. You can set libavcodec (i.e. ffmpeg) options through --ovcopts, see --ovcopts=help for a list.

Please note that mpv's encode mode bypasses mpv's rendering last I checked, so if you're after video rendering quality then you're not getting any advantages over ffmpeg that way (you can use libplacebo as a vf in either ffmpeg or mpv though).

CounterPillow avatar Jan 28 '24 14:01 CounterPillow

Thanks, that's a very helpful response. I'm using MPV primarily as a way of encoding a dynamic playlist for streaming. Not really interested in enhancing the video if that's what you mean. In my build (forked from about 2 years ago) I'm not seeing h264_vaapi in my list of codecs, I'm assuming I need to build it with an additional library? Any idea how I would do that?

twilson90 avatar Jan 28 '24 14:01 twilson90

meson setup -Dvaapi=enabled build to create a meson configuration with vaapi forcibly enabled in ./build. Usually, it is auto-detected if present. You'll also need to have libva installed, and I believe the ffmpeg you build mpv against needs to enable vaapi as well.

In my build (forked from about 2 years ago)

Speaking of meson, that may have been pre-meson, in which case you need to see what the corresponding waf switch was (though in that case it was also autodetected)

CounterPillow avatar Jan 28 '24 14:01 CounterPillow

ffmpeg builds ok with vaapi enabled but mpv is complaining: You manually enabled the feature 'vaapi', but the autodetection check failed.

Log: mpv build log.txt

vainfo:

error: XDG_RUNTIME_DIR not set in the environment.
error: can't connect to X server!
libva info: VA-API version 1.14.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_14
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.14 (libva 2.12.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 22.3.1 ()
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSliceLP
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSliceLP
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointEncPicture
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
      VAProfileVP8Version0_3          : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointVLD

twilson90 avatar Jan 28 '24 15:01 twilson90

hwdec=vaapi-copy

Andarwinux avatar Jan 28 '24 16:01 Andarwinux

@twilson90 Looks like your mpv version is too old to have separated vaapi from X11. Current mpv distinguishes between vaapi on X11, vaapi on DRM and vaapi on Wayland.

@Andarwinux your suggestion is completely unrelated to a build issue.

CounterPillow avatar Jan 28 '24 16:01 CounterPillow

I've got it building with vaapi enabled on an updated version of my fork now, but it's untested. Is there no way to build my older fork with vaapi then?

twilson90 avatar Jan 28 '24 16:01 twilson90

Issues with new build:

root@ns3053860:/opt/mpv-build/mpv/build# ./mpv --hwdec=vaapi --vaapi-device=/dev/dri/renderD128 --o=out.mkv --of=matroska --ovc=h264_vaapi --ovcopts-add=profile=high --ovcopts-add=preset=veryfast --ovcopts-add=level=4 --ovcopts-add=b=4000k --oac=aac --oacopts=ac=2,b=160k "input.mkv"
 (+) Video --vid=1 (*) (h264 1620x1080 30.000fps)
 (+) Audio --aid=1 (*) (aac 2ch 44100Hz)
[hwupload] no hw context
[hwupload] hardware format not supported
[autoconvert] Failed to create HW uploader for format yuv420p
[autoconvert] can't find video conversion for yuv420p
Cannot convert decoder/filter output to any format supported by the output.
Could not initialize video chain.
[vo/lavc] error encoding at EOF
Video: no video
[ao/lavc] Opening encoder: AAC (Advanced Audio Coding) [aac]
AO: [lavc] 44100Hz stereo 2ch floatp

twilson90 avatar Jan 28 '24 16:01 twilson90

You do need to take @Andarwinux 's suggestion. If you are transcoding with no vo, the non-copy hwdec cannot be initialised - it also doesn't offer any benefits, as the whole point of non-copy hwdecs to get zero-copy output to the display.

philipl avatar Jan 28 '24 17:01 philipl

The only benefit I'm after is reducing the load on the CPU and onto the GPU. I've tried --hwdec=vaapi-copy and --vo=gpu (although this should be set by default) and still no luck.

EDIT: I've managed to get ffmpeg transcoding with vaapi, still not sure how to do this with mpv: /opt/mpv-build/ffmpeg_build/ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -i input.mkv -c:v h264_vaapi -b:v 4M -maxrate 4M -rc_mode CQP output.mp4

twilson90 avatar Jan 28 '24 18:01 twilson90

Then you should just keep using ffmpeg. You can basically do anything you want that way, and it's actually intended for transcoding, vs mpv, for which the encoding support is a highly questionable feature.

You can use -vf libplacebo with ffmpeg to get the advanced post-processing you might imagine wanting from mpv.

philipl avatar Jan 29 '24 21:01 philipl

It might be possible to pass the job of encoding to FFMPEG, but not possible for decoding. As I stated earlier, I'm using a single instance of MPV as a sort of dynamic playlist containing various media files, which is transcoded and uploaded to an RTMP server in real-time. I need to be able to change volume, seek, change video / audio filters and lots more, on the fly while transcoding, seamlessly. MPV is a very robust video player and it can do all of this, FFMPEG cannot (without a lot of work). It's currently running and this is the front-end interface, if you're interested: chrome_Zg9491s4gP

twilson90 avatar Jan 29 '24 21:01 twilson90

When used for encoding mpv always uses a special encoding vo. This means that no feature that depends on vo=gpu or vo=gpu-next is going to work. And the zero-copy hwdecs require state provided by the vo. While it's possible to make vo=lavc (the encoder) provide that state (which is basically what ffmpeg is doing), that functionality doesn't exist today, so you will be limited to using vaapi-copy. In practice, that will prevent you from doing a full GPU transcode without bouncing through system memory. But that is unlikely to prevent your workflow from working.

philipl avatar Feb 02 '24 17:02 philipl