Guide: NVDEC Hardware Acceleration Patch for Plex Media Server on Linux

I’m getting the following in my logs - the graphics card is certainly doing heavy lifting, so unsure if it’s something I should worry about and/or it’s some setting in the script I should change.

OS: Fedora

Apr 04, 2019 21:55:05.326 [0x7f951effd700] DEBUG - Codecs: testing h264_qsv (encoder)
Apr 04, 2019 21:55:05.326 [0x7f951effd700] WARN - Failed to find encoder ‘h264_qsv’
Apr 04, 2019 21:55:05.327 [0x7f951effd700] DEBUG - Codecs: testing h264_vaapi (encoder)
Apr 04, 2019 21:55:05.327 [0x7f951effd700] DEBUG - Codecs: hardware transcoding: testing API vaapi
Apr 04, 2019 21:55:05.327 [0x7f951effd700] VERBOSE - [FFMPEG] - Opened VA display via DRM device /dev/dri/renderD128.
Apr 04, 2019 21:55:05.327 [0x7f951effd700] VERBOSE - [FFMPEG] - libva: VA-API version 1.1.0
Apr 04, 2019 21:55:05.327 [0x7f951effd700] VERBOSE - [FFMPEG] - libva: va_getDriverName() returns -1
Apr 04, 2019 21:55:05.327 [0x7f951effd700] ERROR - [FFMPEG] - libva: va_getDriverName() failed with unknown libva error,driver_name=(null)
Apr 04, 2019 21:55:05.327 [0x7f951effd700] ERROR - [FFMPEG] - Failed to initialise VAAPI connection: -1 (unknown libva error).
Apr 04, 2019 21:55:05.327 [0x7f951effd700] DEBUG - Codecs: hardware transcoding: opening hw device failed - probably not supported by this system, error: Input/output error
Apr 04, 2019 21:55:05.327 [0x7f951effd700] DEBUG - Codecs: testing h264_nvenc (encoder)
Apr 04, 2019 21:55:05.328 [0x7f951effd700] VERBOSE - [FFMPEG] - Loaded Nvenc version 8.1
Apr 04, 2019 21:55:05.328 [0x7f951effd700] VERBOSE - [FFMPEG] - Nvenc initialized successfully
Apr 04, 2019 21:55:05.339 [0x7f956999e700] VERBOSE - [TranscodeOutputStream] Waiting 100ms for more data…
Apr 04, 2019 21:55:05.341 [0x7f94f27fc700] DEBUG - Request: [127.0.0.1:45948 (Loopback)] POST /video/:/transcode/session/0yhbor5p67pga597gnq3l6fm/e4f2ebd9-634e-4cde-a31c-887899a46380/seglist?stream=subtitles (24 live) Signed-in
Apr 04, 2019 21:55:05.341 [0x7f94f27fc700] VERBOSE - * Transfer-Encoding => chunked
Apr 04, 2019 21:55:05.341 [0x7f94f27fc700] VERBOSE - * User-Agent => Lavf/58.9.100
Apr 04, 2019 21:55:05.341 [0x7f94f27fc700] VERBOSE - * Accept => /
Apr 04, 2019 21:55:05.341 [0x7f94f27fc700] VERBOSE - * Connection => close
Apr 04, 2019 21:55:05.341 [0x7f94f27fc700] VERBOSE - * Host => 127.0.0.1:32400
Apr 04, 2019 21:55:05.341 [0x7f94f27fc700] VERBOSE - * Icy-MetaData => 1
Apr 04, 2019 21:55:05.341 [0x7f94f27fc700] VERBOSE - * stream => subtitles
Apr 04, 2019 21:55:05.342 [0x7f956999e700] DEBUG - Completed: [127.0.0.1:45948] 200 POST /video/:/transcode/session/0yhbor5p67pga597gnq3l6fm/e4f2ebd9-634e-4cde-a31c-887899a46380/seglist?stream=subtitles (24 live) 0ms 166 bytes
Apr 04, 2019 21:55:05.344 [0x7f951effd700] VERBOSE - [FFMPEG] - 1 CUDA capable devices found
Apr 04, 2019 21:55:05.344 [0x7f951effd700] VERBOSE - [FFMPEG] - [ GPU #0 - < Quadro P2000 > has Compute SM 6.1 ]
Apr 04, 2019 21:55:05.412 [0x7f94f2ffd700] DEBUG - Request: [127.0.0.1:45950 (Loopback)] POST /video/:/transcode/session/0yhbor5p67pga597gnq3l6fm/e4f2ebd9-634e-4cde-a31c-887899a46380/manifest (24 live) Signed-in
Apr 04, 2019 21:55:05.412 [0x7f94f2ffd700] VERBOSE - * Transfer-Encoding => chunked
Apr 04, 2019 21:55:05.412 [0x7f94f2ffd700] VERBOSE - * User-Agent => Lavf/58.9.100
Apr 04, 2019 21:55:05.412 [0x7f94f2ffd700] VERBOSE - * Accept => /
Apr 04, 2019 21:55:05.412 [0x7f94f2ffd700] VERBOSE - * Connection => close
Apr 04, 2019 21:55:05.412 [0x7f94f2ffd700] VERBOSE - * Host => 127.0.0.1:32400
Apr 04, 2019 21:55:05.412 [0x7f94f2ffd700] VERBOSE - * Icy-MetaData => 1
Apr 04, 2019 21:55:05.414 [0x7f94f2ffd700] DEBUG - Transcoder segment range: 0 - 140 (140)
Apr 04, 2019 21:55:05.414 [0x7f956919d700] DEBUG - Completed: [127.0.0.1:45950] 200 POST /video/:/transcode/session/0yhbor5p67pga597gnq3l6fm/e4f2ebd9-634e-4cde-a31c-887899a46380/manifest (24 live) 2ms 166 bytes
Apr 04, 2019 21:55:05.417 [0x7f94f37fe700] DEBUG - Request: [127.0.0.1:45952 (Loopback)] POST /video/:/transcode/session/0yhbor5p67pga597gnq3l6fm/e4f2ebd9-634e-4cde-a31c-887899a46380/seglist?stream=subtitles (24 live) Signed-in
Apr 04, 2019 21:55:05.417 [0x7f94f37fe700] VERBOSE - * Transfer-Encoding => chunked
Apr 04, 2019 21:55:05.417 [0x7f94f37fe700] VERBOSE - * User-Agent => Lavf/58.9.100
Apr 04, 2019 21:55:05.417 [0x7f94f37fe700] VERBOSE - * Accept => /

Hey, I’ve been copy/pasting my own bash script up until now, so I tried out your script since the latest patch. Since I want HEVC/VP8/VP9 content to be HW decoded I posted these argument:

./plex-nvdec-patch.sh -c hevc -c vp8 -c vp9

Since your patch clearly states: “Use -c once per codec”, now when I check the updated Plex Transcoder file, I see the following:

codec="$(get_codec $*)"
if [ $codec == "hevcvp8vp9" ] || [ ]; then
     exec /usr/lib/plexmediaserver/Plex\ Transcoder2 -hwaccel nvdec "$@"
else
     exec /usr/lib/plexmediaserver/Plex\ Transcoder2 "$@"
fi

Did I do something wrong? Or does the script not yet like multiple codec arguments? For now I just applied the default patch and manually removed the H264 argument

So I tried this on my Jetson Nano and plex just crashes every time I try and play a file. I’d like to help debug, but in the meantime, how do I roll this patch back?

I think I figured it out, i just removed -hwaccel nvdec from Plex Transcoder.

tijmenvn,

Make sure you are using bash and not sh. So try running it with bash -c plex-nvdec-patch.sh

William, you can undo the patch via this command:
mv /usr/lib/plexmediaserver/Plex\ Transcoder2 /usr/lib/plexmediaserver/Plex\ Transcoder

I have an Nvidia GT 1030 card which support NVDEC according to the OP . I am running an LXD container with GPU passthrough. Unfortunately, I dont see the transcode using ‘nvdec’. It seems that nvdec is not available,

/usr/lib/plexmediaserver/Plex\ Transcoder2 -hwaccels
Hardware acceleration methods:
cuda
vaapi
cuvid

Nvidia-smi shows that the card is setup properly,


# nvidia-smi 
Sat Apr  6 23:24:18 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.56       Driver Version: 418.56       CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GT 1030     Off  | 00000000:82:00.0 Off |                  N/A |
| 40%   55C    P0    N/A /  30W |      0MiB /  2001MiB |      1%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+
# ls -lh /dev/dri/
total 2.0K
crw-rw---- 1 plex plex 226,   0 Apr  6 21:47 card0
crw-rw---- 1 plex plex 226,   1 Apr  6 21:47 card1
crw-rw---- 1 plex plex 226,   0 Apr  6 21:47 controlD64
crw-rw-rw- 1 plex plex 226, 128 Apr  6 21:47 renderD128

Any idea what could be the issue?

If the CPU is QSV-capable, it will show up first.
Plex looks for card0 and renderD128 as follows

[chuck@lizum ~.353]$ ls -la /dev/dri
total 0
drwxr-xr-x   3 root root        100 Apr  4 16:38 ./
drwxr-xr-x  22 root root       4480 Apr  4 16:38 ../
drwxr-xr-x   2 root root         80 Apr  4 16:38 by-path/
crw-rw----+  1 root video  226,   0 Apr  4 16:38 card0
crw-rw-rw-   1 root render 226, 128 Apr  4 16:38 renderD128
[chuck@lizum ~.354]$ 

You must look at the log files.
It will tell you what the final encoder is.
Plex will always favor the nvenc (nvidia encoder) over QSV encoder.
There is no nVidia decoding at this time.

The CPU is not QSV capable, however I have two video cards,

$ lspci |grep VGA
07:00.0 VGA compatible controller: ASPEED Technology, Inc. ASPEED Graphics Family (rev 30)
82:00.0 VGA compatible controller: NVIDIA Corporation GP108 [GeForce GT 1030] (rev a1)

I dont know whether card0 belongs to Nvidia or the onboard ASPEED.

The log file shows this:

TPU: hardware transcoding: enabled, but no hardware decode accelerator found
TPU: hardware transcoding: zero-copy support not present
TPU: hardware transcoding: final decoder: , final encoder:

Video cards:


# lshw -c video
  *-display                 
       description: VGA compatible controller
       product: ASPEED Graphics Family
       vendor: ASPEED Technology, Inc.
       physical id: 0
       bus info: pci@0000:07:00.0
       version: 30
       width: 32 bits
       clock: 33MHz
       capabilities: vga_controller bus_master cap_list rom
       configuration: driver=ast latency=0
       resources: irq:16 memory:c6000000-c6ffffff memory:c7000000-c701ffff ioport:4000(size=128) memory:c0000-dffff
  *-display
       description: VGA compatible controller
       product: GP108 [GeForce GT 1030]
       vendor: NVIDIA Corporation
       physical id: 0
       bus info: pci@0000:82:00.0
       version: a1
       width: 64 bits
       clock: 33MHz
       capabilities: vga_controller bus_master cap_list rom
       configuration: driver=nvidia latency=0
       resources: irq:35 memory:fa000000-faffffff memory:e0000000-efffffff memory:f0000000-f1ffffff ioport:f000(size=128) memory:fb000000-fb07ffff

How can i make plex use the Nvidia card instead of the ASPEED card?

Is Plex updated to the most recent version? nvdec was added with version PMS 1.15

Yes, I am running Version 1.15.3.876.

I just ran the hwaccels on my end and it also does not show nvdec despite it working.

Just to double check. Do you have the NVIDIA driver installed on both the host and the LXC container? The CUDA libraries need to be available on the container whereas the drivers are needed on the host

I did not have CUDA in the container previously. But now i do,

In the container CUDA is functional,

# /opt/cuda/extras/demo_suite/bandwidthTest
[CUDA Bandwidth Test] - Starting...
Running on...

 Device 0: GeForce GT 1030
 Quick Mode

 Host to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(MB/s)
   33554432                     3073.0

 Device to Host Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(MB/s)
   33554432                     3230.5

 Device to Device Bandwidth, 1 Device(s)
 PINNED Memory Transfers
   Transfer Size (Bytes)        Bandwidth(MB/s)
   33554432                     41002.7

Result = PASS

NOTE: The CUDA Samples are not meant for performance measurements. Results may vary when GPU Boost is enabled.

Transcoder is still not using the acceleration.

DEBUG - TPU: hardware transcoding: enabled, but no hardware decode accelerator found
DEBUG - TPU: hardware transcoding: zero-copy support not present
DEBUG - TPU: hardware transcoding: final decoder: , final encoder:

When using containers, please make this known in the first post. Containers change the environment completely. Many hours of debugging have been wasted by others over this apparently subtle, but important, distinction.

Docker / Container topics should be so tagged server-docker
Native host servers should be tagged server-linux (or however appropriate for the NAS vendor)

All, I have pushed a new update to the script to account for a few things:
-Fixed bug that would not update paths properly if manually defined or if Plex Transcoder is in /usr/lib64
-Changed logic for checking video codec to now hunt for mention of the codec due to various formats of decode input
-Added uninstall option to remove the patch (if it is installed)

I’m not quite sure how to handle a version checking mechanism here and don’t really have the time to see that through (I’m an infrastructure engineer, not a software dev). This update mainly targets the mp4 container issue where the stream selection format is different than the common mkv container. Now the script will check every parameter before the input file to see if it matches the allowed codecs. It’s not the most efficient method, but it makes it so it isn’t dependent on other parameters to ID the decode codec.

I wonder if a simple hack job (I know nothing of software development, so feel free to say if I’m wrong!) of downloading a new version (regardless of current version), and setting appropriate permissions prior to executing it theoretically should suffice for the time being?

tijmenvn, I fixed the issue regarding the multiple defined codecs. I had a syntax error there as well so it was merging strings instead of adding to an array. Please see latest script.

@rajil_s, this can get really nebulous without knowing exactly what is installed on your LXC container and how it is built. Did you also install the nvidia driver itself or just the CUDA toolkit?

@modem7, that method could work. The current script you would download will just act as a front end to download the actual script and run it. My hope is that this script is solid enough at this point that you only need to download it once. (keyword being HOPE)
At a guess, this could be done via a few lines as a separate script:

#!/bin/bash
wget https://raw.githubusercontent.com/revr3nd/plex-nvdec/master/plex-nvdec-patch.sh -O ./plex-nvdec-patch.sh
chmod +x ./plex-nvdec-patch.sh
./plex-nvdec-patch.sh $@

@revr3nd, it is a bare-bones archlinux container. The host itself is running Archlinux with the LXD snap package. I did not install the nvidia driver, only the CUDA package. The full list of installed packages is listed below. The LXD (not lxc) container has the variable set nvidia.runtime: “true” whose function is to “Pass the host NVIDIA and CUDA runtime libraries into the container” as specified here.

The LXD configuration is as follows:

$ lxc config show plex
architecture: x86_64
config:
  image.architecture: amd64
  image.description: Archlinux current amd64 (20190406_04:18)
  image.os: Archlinux
  image.release: current
  image.serial: "20190406_04:18"
  nvidia.runtime: "true"
  volatile.base_image: de43692c92c19e78d99b1168955f629129529599e00adca4256b858473a330e9
  volatile.eth0.name: eth0
  volatile.idmap.base: "0"
  volatile.idmap.next: '[{"Isuid":true,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.idmap: '[{"Isuid":true,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]'
  volatile.last_state.power: RUNNING
devices:
  eth0:
    nictype: bridged
    parent: vlan300br
    type: nic
  gpu:
    gid: "986"
    type: gpu
  sharemedia:
    path: /mnt/media
    source: /mnt/media
    type: disk
ephemeral: false
profiles:
- default
stateful: false
description: ""

List of installed packages in the container,

# pacman -Qe
arch-install-scripts 21-1
autoconf 2.69-5
automake 1.16.1-1
binutils 2.31.1-4
bison 3.3.2-1
cuda 10.1.105-6
dhcpcd 7.0.8-1
diffutils 3.7-1
fakeroot 1.23-1
file 5.36-1
flex 2.6.4-2
gcc 8.2.1+20181127-1
gettext 0.19.8.1-3
git 2.21.0-1
grep 3.3-1
groff 1.22.3-8
gzip 1.10-1
inetutils 1.9.4-7
iproute2 5.0.0-1
iputils 20180629.f6aac8d-4
less 530-1
libtool 2.4.6+42+gb88cebd5-2
licenses 20181104-1
logrotate 3.15.0-1
lshw B.02.18-3
m4 1.4.18-2
make 4.2.1-3
man-db 2.8.5-2
man-pages 5.00-1
nano 4.0-2
netctl 1.20-1
nvidia-utils 418.56-1
openresolv 3.9.0-2
patch 2.7.6-7
pikaur 1.4.1-1
pkgconf 1.6.1-1
plex-media-server-plexpass 1.15.3.876-1
procps-ng 3.3.15-1
psmisc 23.2-1
sed 4.7-1
sudo 1.8.27-1
sysfsutils 2.1.0-10
systemd 241.67-1
systemd-sysvcompat 241.67-1
tar 1.32-1
tautulli 2.1.28-1
texinfo 6.6-1
vi 1:070224-3
wget 1.20.2-1
which 2.21-3

Inside the container the nvidia device has the correct permissions,

[root@plex ~]# ls -lh /dev/dri/
total 2.0K
crw-rw---- 1 root video 226,   0 Apr  7 10:12 card0
crw-rw---- 1 root video 226,   1 Apr  7 10:12 card1
crw-rw---- 1 root video 226,   0 Apr  7 10:12 controlD64
crw-rw-rw- 1 root video 226, 128 Apr  7 10:12 renderD128
[root@plex ~]# ls -lh /dev/nv* 
crw-rw-rw- 1 nobody nobody 235,   0 Apr  7 10:06 /dev/nvidia-uvm
crw-rw-rw- 1 nobody nobody 235,   1 Apr  7 10:06 /dev/nvidia-uvm-tools
crw-rw-rw- 1 root   video  195,   0 Apr  7 10:12 /dev/nvidia0
crw-rw-rw- 1 nobody nobody 195, 255 Apr  6 21:11 /dev/nvidiactl
[root@plex ~]#

The log shows this:

[root@plex Logs]# grep FFMPEG  Plex\ Media\ Server.log 
Apr 07, 2019 17:18:34.415 [0x7f93f27fc700] ERROR - [FFMPEG] - OpenEncodeSessionEx failed: unsupported device (2)
Apr 07, 2019 17:18:34.440 [0x7f93f27fc700] ERROR - [FFMPEG] - No NVENC capable devices found
Apr 07, 2019 17:18:34.441 [0x7f93f27fc700] ERROR - [FFMPEG] - libva: va_getDriverName() failed with unknown libva error,driver_name=(null)
Apr 07, 2019 17:18:34.441 [0x7f93f27fc700] ERROR - [FFMPEG] - Failed to initialise VAAPI connection: -1 (unknown libva error).
Apr 07, 2019 17:18:34.623 [0x7f93f27fc700] ERROR - [FFMPEG] - OpenEncodeSessionEx failed: unsupported device (2)
Apr 07, 2019 17:18:34.648 [0x7f93f27fc700] ERROR - [FFMPEG] - No NVENC capable devices found
Apr 07, 2019 17:18:34.649 [0x7f93f27fc700] ERROR - [FFMPEG] - libva: va_getDriverName() failed with unknown libva error,driver_name=(null)
Apr 07, 2019 17:18:34.649 [0x7f93f27fc700] ERROR - [FFMPEG] - Failed to initialise VAAPI connection: -1 (unknown libva error).
Apr 07, 2019 17:18:34.936 [0x7f93f27fc700] ERROR - [FFMPEG] - OpenEncodeSessionEx failed: unsupported device (2)
Apr 07, 2019 17:18:34.962 [0x7f93f27fc700] ERROR - [FFMPEG] - No NVENC capable devices found
Apr 07, 2019 17:18:34.963 [0x7f93f27fc700] ERROR - [FFMPEG] - libva: va_getDriverName() failed with unknown libva error,driver_name=(null)
Apr 07, 2019 17:18:34.963 [0x7f93f27fc700] ERROR - [FFMPEG] - Failed to initialise VAAPI connection: -1 (unknown libva error).
Apr 07, 2019 17:18:35.224 [0x7f93f27fc700] ERROR - [FFMPEG] - OpenEncodeSessionEx failed: unsupported device (2)
Apr 07, 2019 17:18:35.249 [0x7f93f27fc700] ERROR - [FFMPEG] - No NVENC capable devices found
Apr 07, 2019 17:18:35.250 [0x7f93f27fc700] ERROR - [FFMPEG] - libva: va_getDriverName() failed with unknown libva error,driver_name=(null)
Apr 07, 2019 17:18:35.250 [0x7f93f27fc700] ERROR - [FFMPEG] - Failed to initialise VAAPI connection: -1 (unknown libva error).
Apr 07, 2019 17:18:35.509 [0x7f93f27fc700] ERROR - [FFMPEG] - OpenEncodeSessionEx failed: unsupported device (2)
Apr 07, 2019 17:18:35.534 [0x7f93f27fc700] ERROR - [FFMPEG] - No NVENC capable devices found
Apr 07, 2019 17:18:35.535 [0x7f93f27fc700] ERROR - [FFMPEG] - libva: va_getDriverName() failed with unknown libva error,driver_name=(null)
Apr 07, 2019 17:18:35.535 [0x7f93f27fc700] ERROR - [FFMPEG] - Failed to initialise VAAPI connection: -1 (unknown libva error).
Apr 07, 2019 17:18:35.795 [0x7f93f27fc700] ERROR - [FFMPEG] - OpenEncodeSessionEx failed: unsupported device (2)
Apr 07, 2019 17:18:35.820 [0x7f93f27fc700] ERROR - [FFMPEG] - No NVENC capable devices found
Apr 07, 2019 17:18:35.821 [0x7f93f27fc700] ERROR - [FFMPEG] - libva: va_getDriverName() failed with unknown libva error,driver_name=(null)
Apr 07, 2019 17:18:35.821 [0x7f93f27fc700] ERROR - [FFMPEG] - Failed to initialise VAAPI connection: -1 (unknown libva error).

Thank you very much! I will try the renewed script with the next Plex Server update ;). I did not know using bash or sh made a difference?

@rajil_s Try using the following guide from @constiens : Plex HW acceleration in LXC container - anyone with success?

He posted a step-by-step guide to succesfully implement HW transcoding (encoding officially :p) for Nvidia GPU’s in LXC container. Using Proxmox as hypervisor in his (and also mine) usecase. Not the same, but maybe has something there that could help

1 Like

Beautiful! Thank you so much. It works perfectly now.

/usr/lib/plexmediaserver/Plex Transcoder2 -hwaccel nvdec -codec:#0x02 h264 -codec:#0x01 aac 
1 Like