jellyfin-server-freebsd icon indicating copy to clipboard operation
jellyfin-server-freebsd copied to clipboard

Is hardware acceleration possible?

Open frusanov opened this issue 3 years ago • 43 comments

Is hardware acceleration possible with this solution? Can you please add information about it in readme, i think it be very helpful.

frusanov avatar Feb 07 '22 13:02 frusanov

It should work as long as: the kernel supports it (either directly or via modules), ffmpeg is compiled to support it, and the jail is able to expose the hardware correctly.

Unfortunately, I don't have any hardware to test support. My FreeBSD servers don't have any commodity hardware in them and NVIDIA Tesla-series cards are poorly supported by NVIDIA under FreeBSD.

Thefrank avatar Feb 07 '22 17:02 Thefrank

What device would need to be passed on TrueNAS to get an AMD CPU with an iGPU to do hardware acceleration?

RossComputerGuy avatar Nov 21 '22 04:11 RossComputerGuy

drm-kmod or drm-510-kmod should work. the jail will need dri* and drm* exposed

Thefrank avatar Nov 21 '22 05:11 Thefrank

There's no dri* and drm* devices in /dev on TrueNAS.

RossComputerGuy avatar Nov 21 '22 05:11 RossComputerGuy

does lspci list it? If yes, make sure the kernel module is loaded correctly.

Thefrank avatar Nov 21 '22 05:11 Thefrank

Yes, I see the device. How do you load kernel modules on TrueNAS? There's no modprobe like on Linux.

RossComputerGuy avatar Nov 21 '22 05:11 RossComputerGuy

kldstat for listing kldload to load kldunload for unloading https://www.freebsd.org/cgi/man.cgi?query=kld&sektion=4

Thefrank avatar Nov 21 '22 06:11 Thefrank

Those modules don't exist on TrueNAS.

RossComputerGuy avatar Nov 21 '22 06:11 RossComputerGuy

oh yeah TrueNAS. It might have drm and something like amdgpu. If not, you have a much harder task of adding it back in every time TrueNAS restarts and every time you update it.

Thefrank avatar Nov 21 '22 06:11 Thefrank

Have a look at https://github.com/kern2011/Freenas-Quicksync. The instructions are for Plex on FreeNAS 11.3, but the driver loading and devfs ruleset creation should be the same.

You will probably also need to install the VAAPI packages for your GPU inside the jail.

michaelburton avatar Nov 30 '22 10:11 michaelburton

Ok, I have drm.ko and I loaded it. I have a lot of AMD GPU modules for my CPU. image Which modules will I need to load? I loaded them all by hand and I have a lot of devices in /dev/drm (257 in total).

RossComputerGuy avatar Dec 01 '22 04:12 RossComputerGuy

@michaelburton That guide is a bit out of date for TrueNAS Core 13.0-U3.1. I've spend the past 30 minutes trying to get /dev/drm to show up and it never doesn.

RossComputerGuy avatar Dec 01 '22 05:12 RossComputerGuy

The instructions assume an Intel GPU. I don't have an AMD GPU to test with, and have no idea if it's possible at all.

michaelburton avatar Dec 01 '22 06:12 michaelburton

I think I got it, I was able to get /dev/drm to show up in the jail. I get about 41 FPS with trancoding "2001: A Space Odyssey". image In the ffmpeg log, I see this

Stream mapping:
  Stream #0:0 -> #0:0 (hevc (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (dts (dca) -> aac (native))

These are my settings for transcoding. image

RossComputerGuy avatar Jan 06 '23 01:01 RossComputerGuy

The log for ffmpeg should have something about hwaccel type (e.g., Using cuda hwaccel type dxva2 with new default device)

Thefrank avatar Jan 06 '23 17:01 Thefrank

I don't see that in the logs, also ffmpeg -hwaccels shows only 3 options: vdpau, vaapi, and drm.

RossComputerGuy avatar Jan 07 '23 23:01 RossComputerGuy

There should be a noticeable difference (e.g., time to encode or CPU usage when de/encoding) between using and not using hwaccel

emby has a nice hw detection tool that you can try: https://mediabrowser.github.io/embytools/ffdetect-2022_05_07-x64_freebsd13.tar.xz It is however designed for FreeBSD and not FreeNAS/TrueNAS

Thefrank avatar Jan 08 '23 00:01 Thefrank

It won't be DXVA because that's Windows-specific.

You'll probably have to install the libva-vdpau-driver package inside your jail and use the libva acceleration option in your Jellyfin settings. Again, I don't have an AMD GPU so I have no idea if this will work.

michaelburton avatar Jan 08 '23 03:01 michaelburton

It won't be DXVA because that's Windows-specific.

Yeah that was a bad example. I only have a GPU that can hwaccel in a Windows box right now and checked the output there >.< It should show something about it using hwaccel though

Thefrank avatar Jan 09 '23 01:01 Thefrank

I can confirm that hardware encoding is working on Intel Gpu so it should work with Amd with the va drivers. Here's what I needed to do to make it work.

First in the JellyFin jail install theses packages :

pkg install libva-utils
pkg install libva-vdpau-driver
pkg install libva-intel-media-driver

Then on the host (ouside the jail) create a script file with this content :

#!/bin/sh

echo '[devfsrules_bpfjail=101]
add path 'bpf*' unhide

[plex_drm=10]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_jail
add include $devfsrules_bpfjail
add path 'dri*' unhide
add path 'dri/*' unhide
add path 'drm*' unhide
add path 'drm/*' unhide' >> /etc/devfs.rules

service devfs restart

# Uncomment the correct line for intel vs amd drivers
#kldload /boot/modules/i915kms.ko # Intel
kldload /boot/modules/radeonkms.ko # Amd

It could be placed in the root user like /root/enable_hardware_encode_script.sh Then make it executable : chmod +x /root/enable_hardware_encode_script.sh and run the script : /root/enable_hardware_encode_script.sh

Now stop the jail and edit it. In the Jail Properties change the devfs_ruleset to 10 save then start the jail. Open the jail shell and make sure that vainfo returns at least : VAProfileH264Main : VAEntrypointEncSlice

Now hardware encoding with libva should work. But JellyFin will probably crash with an error about a non initialised gpu. I had to add a little script.

spz2k9 avatar Jan 31 '23 01:01 spz2k9

Here's the script to fix ffmpeg I'm not a python expert so I took inspiration from rffmpeg to make it work. The script will need to be added in the JellyFin jail at /usr/local/bin/lffmpeg.

#!/usr/bin/env python3.9

import subprocess
import sys

from subprocess import run, PIPE

#Fix missing ffmpeg init error on BSD Jellyfin
def add_missing_params(args):
        args.insert(0, 'vaapi')
        args.insert(0, '-hwaccel')
        args.insert(0, 'ffmpeg')

def run_ffmpeg(args):
        add_missing_params(args)
        print("args: ", args)
        subprocess.run(args)

# Entrypoint
all_args = sys.argv

cmd_name = all_args[0]
ffmpeg_args = all_args[1:]

run_ffmpeg(ffmpeg_args)

Once the script is created and made executable with chmod +x /usr/local/bin/lffmpeg, you'll have to tell JellyFin to use this one for transcoding in the Server--­>Playback--­>"FFmpeg path" option.

If everything work you can now add the "/root/enable_hardware_encode_script.sh" script PostInit script in the TrueNas Core UI in Tasks --­> Init / Shutdown.

spz2k9 avatar Jan 31 '23 01:01 spz2k9

Big thanks to @Thefrank for the BSD package.

spz2k9 avatar Jan 31 '23 01:01 spz2k9

@spz2k9 thats a pretty cool solution! Would you be willing to make a PR here with that information?

Thefrank avatar Jan 31 '23 03:01 Thefrank

Yes, I can check tomorrow for a PR. I'll only include Intel for now since Amd gpu hasn't been confirmed yet.

spz2k9 avatar Jan 31 '23 03:01 spz2k9

You can do the same thing as that Python script using the shell:

#!/bin/sh
ffmpeg -hwaccel vaapi "$@"

Unfortunately my Ivy Bridge CPU is too old for libva-intel-media-driver, and I get an immediate kernel panic when trying to encode using libva-intel-driver instead, so I can't provide any further feedback.

michaelburton avatar Jan 31 '23 08:01 michaelburton

You can do the same thing as that Python script using the shell:

#!/bin/sh
ffmpeg -hwaccel vaapi "$@"

Unfortunately my Ivy Bridge CPU is too old for vaapi-intel-media-driver, and I get an immediate kernel panic when trying to encode using libva-intel-driver instead, so I can't provide any further feedback.

I don't know... my 4th gen intel isn't all that new and it will do h264 encoding. If I check ffmpeg page here. It states that Ivy Bridge has h264 encoding.

One thing I didn't note in the pull request... and it's hard to know if everything is really required... but maybe you could try changing thoses settings in the BIOS :

  • Force the default GPU to 'Integrated' instead of Auto or first PCI-E.
  • Allocate 128Mb ram to the Integrated GPU with 256Mb as it's pool
  • Then... plug a monitor in the HDMI.

I also had kernel panic with TrueNas Core before doing thoses changes.... but It was working fine with a Windows 10 VM running on TrueNas Core... so I was sure there was a way to make it work... took a lot of time to find all the settings. Now I'm using a cheap Dummy HDMI on my integrated gpu... might not be needed but it works and it's like 8$.

spz2k9 avatar Jan 31 '23 20:01 spz2k9

https://en.wikipedia.org/wiki/Intel_Core

need to have a 4th gen I-series* or newer Intel CPU AFAIK edit typo

This is far more of a mess than I thought: https://github.com/intel/media-driver#decodingencoding-features

Thefrank avatar Jan 31 '23 21:01 Thefrank

* Then... plug a monitor in the HDMI.

Looks like that made the difference for me, and I'll be adding a dummy HDMI plug to my shopping list. Thanks.

The user that Jellyfin runs as also needs to be a member of the video group so that it has access to the contents of /dev/drm.

There are two different Intel VAAPI driver packages available, libva-intel-media-driver works with Broadwell (5th gen Core) and newer iGPUs, libva-intel-driver works with older iGPUs including Sandy/Ivy Bridge and Haswell.

I've also been digging into the Jellyfin source to figure out why -init_hw_device and -hwaccel weren't being included in the ffmpeg arguments in the first place. The problem is that they check OperatingSystem.IsLinux() as part of some of the VAAPI-related setup, e.g. in MediaBrowser.MediaEncoding.Encoder.MediaEncoder.SetFFmpegPath, MediaBrowser.MediaEncoding.Encoder.EncoderValidator.CheckVaapiDeviceByDriver, MediaBrowser.Controller.MediaEncoding.EncodingHelper.GetHwaccelType among others.

I could potentially write a pull request to add a bunch of || OperatingSystem.IsFreeBSD() where necessary, but I don't know whether the upstream project would accept them given that FreeBSD isn't officially supported.

michaelburton avatar Feb 01 '23 15:02 michaelburton

Yes the information is hard to gather but it seems more like a 3rd gen and up... but driver compatibility might difer from Windows / linux / bsd.

I think I'll do another pull request to add the info at the end in the Troubleshooting section.

spz2k9 avatar Feb 01 '23 17:02 spz2k9

@michaelburton its worth a shot to open a PR with Jellyfin, but to be completely straightforward, it is unlikely to get merged as they do not officially support it. I would not mind being wrong :) Worst case is that you can just make a patch out of it and put it on this repo for GPL compliance.

I can also generate test builds manually.

Thefrank avatar Feb 01 '23 22:02 Thefrank