Thefrank / jellyfin-server-freebsd

jellyfin-server component for freebsd
185 stars 16 forks source link

Is hardware acceleration possible? #13

Open frusanov opened 2 years ago

frusanov commented 2 years ago

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

Thefrank commented 2 years ago

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.

RossComputerGuy commented 1 year ago

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

Thefrank commented 1 year ago

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

RossComputerGuy commented 1 year ago

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

Thefrank commented 1 year ago

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

RossComputerGuy commented 1 year ago

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

Thefrank commented 1 year ago

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

RossComputerGuy commented 1 year ago

Those modules don't exist on TrueNAS.

Thefrank commented 1 year ago

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.

michaelburton commented 1 year ago

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.

RossComputerGuy commented 1 year ago

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 commented 1 year ago

@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.

michaelburton commented 1 year ago

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.

RossComputerGuy commented 1 year ago

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

Thefrank commented 1 year ago

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

RossComputerGuy commented 1 year ago

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

Thefrank commented 1 year ago

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

michaelburton commented 1 year ago

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.

Thefrank commented 1 year ago

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

spz2k9 commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

Big thanks to @Thefrank for the BSD package.

Thefrank commented 1 year ago

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

spz2k9 commented 1 year ago

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

michaelburton commented 1 year ago

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.

spz2k9 commented 1 year ago

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 :

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$.

Thefrank commented 1 year ago

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

michaelburton commented 1 year ago
* 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.

spz2k9 commented 1 year ago

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.

Thefrank commented 1 year ago

@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.

spz2k9 commented 1 year ago

The ffmpeg version they rely on is 5.0+(you can check on their official docker url), BSD seems to be 4.4.3. I know there's been a lot for cmd line change with 5.0... most script got broken on windows... so I think they'll probably just say it's an old version and not supported.

spz2k9 commented 1 year ago

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.

Yes... you're right, I think I forgot to include it in the documentation.

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.

I completely misread that yesterday. I think they should just limit the dropdown options to that the OS offer rather than plaster the OS capability everywhere. VAAPI should only appear on BSD / Linux so if the option is only available on theses system they would not have to check for the command line options everytime.

ageekhere commented 1 year ago

I have an amd 5600g, what can I try to get hardware acceleration working? I have enabled AMD AMF but it seems to still use CPU for transcoding.

Update 1: Looking at the wiki https://jellyfin.org/docs/general/administration/hardware-acceleration/ it says "Jellyfin 10.9 enables full acceleration for AMD Vega and newer GPUs on Linux via VA-API and Vulkan interop."

Update2: Following guide Installation_TrueNAS_GUI vainfo Error error Going to go though the guide again in cause i missed something

Update 3: Script returns can't load /boot/modules/radeonkms.ko: module already loaded or in kernel Only drm now shows under dev no dri and jellyfin needs to use /dev/dri/renderD128

Ok so the script for amd enable_gpu_jails.sh does not unhide dri

spz2k9 commented 1 year ago

5600g... might not be supported yet. Truenas drivers are kinda old. Can you post a copy of dmesg we'll see what gets detected.

ageekhere commented 1 year ago

5600g... might not be supported yet. Truenas drivers are kinda old. Can you post a copy of dmesg we'll see what gets detected.

dmesg.txt

spz2k9 commented 1 year ago

I've checked the logfile and there's no sign of radeonkms in it... there's only a generic vga...

vgapci0:

If it's the only one detected it could be the problem... maybe post the result of 'lspci -v' and a 'kldstat' that way we'll be able to see the all the modules got loaded correctly even if the script says the modules were loaded.

Also, I've seen posts where 5*00g GPU got mis detected by the driver... and it required an updated driver.

ageekhere commented 1 year ago

results of lspci -v and kldstat on Truenas core shell kldstat.txt lspciOutput.txt

Thefrank commented 1 year ago

pciconf -lv | grep -i vga is usually a bit more informative than lspci -v but it looks like the version of drivers are before that graphics chip was supported.

This is not an issue on stock FreeBSD as installing https://www.freshports.org/graphics/drm-510-kmod + https://www.freshports.org/graphics/gpu-firmware-amd-kmod should allow it work fine...HOWEVER it does not list Zen3 Cezanne (or above) AND you cant really do that on TrueNAS anyways

ageekhere commented 1 year ago

@Thefrank Thanks, so to conclude The current amd GPU drivers in Truenas Core are too old to support the 5600g GPU.

So have we hit a roadblock? is there anything else can that be tried or do i just need to wait for truenas core to update the amd drivers?

Thefrank commented 1 year ago

@ageekhere Well, it should work with the correct drivers under FreeBSD 13.1+ (see here: https://bsd-hardware.info/?id=cpu:amd-25-80-0-ryzen-5-5600g-with-radeon-graphics) but might not work WELL (e.g., might output graphics in a desktop environment but might not work for hwaccel)

Trying to replace/change out kernel modules in TrueNAS is complex and likely to end in tears

edit: exact listing for JUST the graphics working/detected https://bsd-hardware.info/?id=pci:1002-1638-1002-1636

ageekhere commented 1 year ago

Trying to replace/change out kernel modules in TrueNAS is complex and likely to end in tears

Agreed, I can also add a GPU to the Truenas server at a later date.

ageekhere commented 1 year ago

For completeness here is the output for pciconf -lv | grep -i vga log

Thefrank commented 1 year ago

and for future people...that relates to: https://bsd-hardware.info/?id=pci:1002-1638-1458-d000 which as of posting does not appear to be supported under TrueNAS, FreeBSD, or OPNSense.