Wednesday 12 September 2018

Plex hardware accelerated transcoding within LXC

I run Plex Media Server within an LXC container on my NAS. The NAS itself is a QNAP TS-251+ but it is running Debian 9. I have all the functions I use separated into individual LXC containers.

Plex runs quite well considering the low powered Celeron J1900 processor, but it does tend to struggle with HD transcoding. I managed to get GPU assisted transcoding working this evening which appears to help considerably!

Here are the requirements:
https://support.plex.tv/articles/115002178853-using-hardware-accelerated-streaming/

Fortunately the Celeron J1900 supports Intel Quick Sync Video.

First of all I checked the host could see the DRI stuff:

tim@host:~$ journalctl
Jul 16 21:29:30 jupiter kernel: [drm] Initialized i915 1.6.0 20160919 for 0000:00:02.0 on minor 0

tim@host:~$ ls -l /dev/dri
total 0
crw-rw---- 1 root video 226,   0 Jul 16 21:29 card0
crw-rw---- 1 root video 226,  64 Jul 16 21:29 controlD64
crw-rw---- 1 root video 226, 128 Jul 16 21:29 renderD128

I then tried mapping the devices through to the container:

tim@host:~$ sudo vi /var/lib/lxc/plex/config
...
lxc.mount.entry = /dev/dri dev/dri none bind,create=dir 0 0

I restarted the container then installed the relevant driver and the vainfo program within it:

tim@plex:~$ sudo apt-get install i965-va-driver vainfo

Both the Plex user and my user were in the video group yet vainfo was just saying 'Abort' instead of giving any useful info. I did some further digging:

tim@plex:~$ strace vainfo
...
open("/dev/dri/renderD128", O_RDWR)     = -1 EPERM (Operation not permitted)
open("/dev/dri/card0", O_RDWR)          = -1 EPERM (Operation not permitted)
...

The container did not have permissions to talk to those devices.

I did a bit of reading on control groups and device numbers and came up with the following rule to allow the container to use any character device with a major number of 226 (Direct Rendering Infrastructure):

tim@host:~$ sudo vi /var/lib/lxc/plex/config
...
lxc.cgroup.devices.allow = c 226:* rw
lxc.mount.entry = /dev/dri dev/dri none bind,create=dir 0 0

After stopping and starting the container, I could now run vainfo successfully:

tim@plex:~$ vainfo
error: XDG_RUNTIME_DIR not set in the environment.
error: can't connect to X server!
libva info: VA-API version 0.39.4
libva info: va_getDriverName() returns 0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/i965_drv_video.so
libva info: Found init function __vaDriverInit_0_39
libva info: va_openDriver() returns 0
vainfo: VA-API version: 0.39 (libva 1.7.3)
vainfo: Driver version: Intel i965 driver for Intel(R) Bay Trail - 1.7.3
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Simple            : VAEntrypointEncSlice
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileH264StereoHigh         : VAEntrypointVLD
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc
      VAProfileJPEGBaseline           : VAEntrypointVLD