jellyfin-server-freebsd
jellyfin-server-freebsd copied to clipboard
Is hardware acceleration possible?
Is hardware acceleration possible with this solution? Can you please add information about it in readme, i think it be very helpful.
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.
What device would need to be passed on TrueNAS to get an AMD CPU with an iGPU to do hardware acceleration?
drm-kmod
or drm-510-kmod
should work. the jail will need dri*
and drm*
exposed
There's no dri*
and drm*
devices in /dev
on TrueNAS.
does lspci
list it? If yes, make sure the kernel module is loaded correctly.
Yes, I see the device. How do you load kernel modules on TrueNAS? There's no modprobe
like on Linux.
kldstat
for listing
kldload
to load
kldunload
for unloading
https://www.freebsd.org/cgi/man.cgi?query=kld&sektion=4
Those modules don't exist on TrueNAS.
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.
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.
Ok, I have drm.ko
and I loaded it. I have a lot of AMD GPU modules for my CPU.
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).
@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.
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.
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".
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.
The log for ffmpeg
should have something about hwaccel type
(e.g., Using cuda hwaccel type dxva2 with new default device
)
I don't see that in the logs, also ffmpeg -hwaccels
shows only 3 options: vdpau
, vaapi
, and drm
.
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
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.
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
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.
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.
Big thanks to @Thefrank for the BSD package.
@spz2k9 thats a pretty cool solution! Would you be willing to make a PR here with that information?
Yes, I can check tomorrow for a PR. I'll only include Intel for now since Amd gpu hasn't been confirmed yet.
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.
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 usinglibva-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$.
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
* 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.
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.
@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.