Got HW Transcoding to work with libva/vaapi on Ryzen APU (Ryzen 7 4700U)

Hey there,

I’ve read a lot of comments stating that Plex HW transcoding can not be made to work with the vaapi APIs exported by AMD APUs with integrated graphics. This is true, at least looking at how Plex sets things up out of the box.

Manually copying over the libva drivers for AMD GPUs plus related shared libraries fixed the problem for me.

 cp /lib/x86_64-linux-gnu/dri/radeonsi_drv_video.so /usr/lib/plexmediaserver/lib/dri/ && \
 cp /lib/x86_64-linux-gnu/libdrm_amdgpu.so.1.* /usr/lib/plexmediaserver/lib/libdrm_amdgpu.so.1 && \
 cp /lib/x86_64-linux-gnu/libdrm.so.2.* /usr/lib/plexmediaserver/lib/libdrm.so.2 && \
 cp /lib/x86_64-linux-gnu/libva-drm.so.2.* /usr/lib/plexmediaserver/lib/libva-drm.so.2 && \
 cp /lib/x86_64-linux-gnu/libva.so.2.* /usr/lib/plexmediaserver/lib/libva.so.2 && \
 cp /lib/x86_64-linux-gnu/libstdc++.so.6.* /usr/lib/plexmediaserver/lib/libstdc++.so.6

Running the whole shebang in a Docker container also checks out, here’s my patch for the linuxserver.io Plex container (apply the patch and rebuild the container)

Let me know if this works for you Ryzen APU users out there too.

Jan 10, 2021 05:31:57.500 [0x7f31977fe700] Debug — [Transcode] Codecs: hardware transcoding: testing API vaapi
Jan 10, 2021 05:31:57.514 [0x7f31977fe700] Debug — [Transcode] TPU: hardware transcoding: final decoder: vaapi, final encoder: vaapi
Jan 10, 2021 05:31:57.514 [0x7f31977fe700] Debug — [Transcode] Job running: EAE_ROOT='/tmp/pms-xxxxx/EasyAudioEncoder' FFMPEG_EXTERNAL_LIBS='/config/Library/Application\ Support/Plex\ Media\ Server/Codecs/367b3d4-3654-linux-x86_64/' LIBVA_DRIVERS_PATH='/usr/lib/plexmediaserver/lib/dri' XDG_CACHE_HOME='/config/Library/Application Support/Plex Media Server/Cache' XDG_DATA_HOME='/usr/lib/plexmediaserver/Resources' X_PLEX_TOKEN=xxx' '/usr/lib/plexmediaserver/Plex Transcoder' '-codec:0' 'h264' '-hwaccel:0' 'vaapi' '-hwaccel_fallback_threshold:0' '10' '-hwaccel_output_format:0' 'vaapi' '-hwaccel_device:0' 'vaapi' '-codec:1' 'aac_latm' '-live_start_index' '0' '-probesize' '20000000' '-i' 'http://127.0.0.1:32400/livetv/sessions/1173c1ab-80a9-4198-87d0-33ec938b57ae/xxxx/index.m3u8?offset=22.797632&X-Plex-Incomplete-Segments=1&X-Plex-Token=xxxxxxxxxxxxxxxxxxxx' '-filter_complex' '[0:0]hwupload[0];[0]deinterlace_vaapi[1];[1]scale_vaapi=w=1920:h=1080:format=nv12[2];[2]hwupload[3]' '-filter_complex' '[0:1] aresample=async=1:ocl='\''stereo'\'':rematrix_maxval=0.000000dB:osr=48000[4]' '-map' '[3]' '-codec:0' 'h264_vaapi' '-b:0' '8403k' '-maxrate:0' '11205k' '-bufsize:0' '22410k' '-r:0' '25' '-force_key_frames:0' 'expr:gte(t,0+n_forced*1)' '-map' '[4]' '-metadata:s:1' 'language=eng' '-codec:1' 'aac' '-b:1' '151k' '-segment_format' 'mpegts' '-f' 'ssegment' '-individual_header_trailer' '0' '-segment_time' '1' '-segment_start_number' '0' '-segment_time_delta' '0.25' '-segment_list' 'http://127.0.0.1:32400/video/:/transcode/session/xxxx/13b6d97a-5b89-42b6-97c7-2c3993bf6fbc/seglist?X-Plex-Http-Pipeline=infinite' '-segment_list_type' 'csv' '-segment_list_size' '5' '-segment_list_separate_stream_times' '1' '-segment_list_unfinished' '1' '-max_delay' '5000000' '-map_metadata' '-1' '-map_chapters' '-1' 'media-%05d.ts' '-init_hw_device' 'vaapi=vaapi:' '-filter_hw_device' 'vaapi' '-y' '-nostats' '-loglevel' 'quiet' '-loglevel_plex' 'error' '-xioerror' '-progressurl' 'http://127.0.0.1:32400/video/:/transcode/session/xxxx/13b6d97a-5b89-42b6-97c7-2c3993bf6fbc/progress'

Cheers,
Sebastian

27 Likes

@mauimauer

Thanks for that.

From what you supplied, it looks like it only supports the onboard GPU.
Is this correct?

If so, do you happen to know what it would take to support all capable Radeon GPU cards (of which there are many out there)? I ask because you did include radeonsi_drv

May I also have the DEBUG log ZIP file which captures this entire sequence?
( I’m looking from the point of the MDE through FFMPEG launch )

Sure happy to share a debug log. Just let me know where to drop it.
I believe this should work with most recent AMD architectures that properly expose their capabilities trough vaapi (However I did not test with any other device, this Ryzen APU is my first team red system in a while).

I have validated actual GPU usage by looking at radeontop metrics. Plex itself also shows the (hw) tag.

Check your PM

The Ryzen is a real CPU again. :slight_smile:
Ignore the marketing label LOL

tos_1080p_ts hevc_transcode

This is fantastic!

I have an 280X and Vega64. Will try to find some time to throw them in and test this during the week for h264 and h265 for 4k -> 1080p.

I suspect the 280x hardware may not be able to do h265?

I am not sure about the 280x. The currently used core for recent APUs (Renoir in my case) seem to handle h265just fine and transcode 4K HEVC to h264 without a hitch. Some of the support will also be dependant to what version of libmesa/gallium/dri-radeon etc. your system uses.

Hope someone can repro my results. Be sure to use radeontop (or something like that) to validate GPU load on transcoding.

My system is Xen with passthrough to a Kubernetes host running in a domU (aka VM). I know Nvidia has a solid setup for this when running containers; however, I do expect to be venturing into some untested territory here. Hence the advantage to Xen: I can spin-up another domU running Ubuntu or something and pass the GPU(s) through that way, then run the same docker image.

For testing, I was going to throw Ubuntu onto an USB to boot an older machine and pull down that docker image you linked to, and patch it, to test.

Awesome! Thanks a ton! Finally hw transcoding on my Renoir APU.
I’m running Plex in a LXC container on a Proxmox system with GPU Passthrough. I had to switch my container to privileged and copy the files from /usr/lib/x68_64… to the destination folder.

Have you tried HDR files? For me Plex is still using the CPU with 4k HEVC HDR files. Non-HDR 4k are fine (like in your screenshot).

Logs for HDR files:

Error — [Transcoder] [AVHWDeviceContext @ 0x25c3bc0] No matching devices found.
Error — [Transcoder] [Parsed_hwmap_2 @ 0x2594140] Failed to created derived device context: -19.
Error — [Transcoder] [Parsed_hwmap_2 @ 0x2594140] Failed to configure output pad on Parsed_hwmap_2
Error — [Transcoder] Error reinitializing filters!
Error — [Transcoder] Failed to inject frame into filter network: No such device
Error — [Transcoder] Error while processing the decoded data for stream #0:0

Yeah, that’s where the hope lies with the Plex Transcoder team, fancier features like HDR are likely to be buggy, this could be on the Plex or Mesa/Gallium side.

I suggest you try to play around with newer mesa/gallium/kernel versions. I am able to get HW transcoding for most HEVC 10bit files I’ve tested.

Make sure to check your vainfo

5.10.4-051004-generic

vainfo: VA-API version: 1.7 (libva 2.6.0)
vainfo: Driver version: Mesa Gallium driver 21.1.0-devel for AMD RENOIR (DRM 3.40.0, 5.10.4-051004-generic, LLVM 11.0.1)
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileHEVCMain10             : VAEntrypointVLD
      VAProfileHEVCMain10             : VAEntrypointEncSlice
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileVP9Profile0            : VAEntrypointVLD
      VAProfileVP9Profile2            : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc

Ah ok. My vainfo output looks the same (except I’m on a lower kernel).
I was just curious if the problem was on my side. I’ve got only 4 files with HDR so right now it’s not important at all. All the other files are working fine and I’m super happy about it! Thanks again!

Edit: HDR files work if you untick the Enable HDR tone mapping option in the transcoder settings.

1 Like

I can confirm this is working for me as well. Excellent news!

2 Likes

For those of us less technically inclined, how do I go about setting all this up? I’d like to set my 1650 free and use my Ryzen 3 3200g Radeon Vega 8 as the hardware encoder of choice so I can assign the 1650 to a VM.

Should I backup my current Plex container first? I am running my Plex container on unRAID server.

1 Like

Could you detail exactly what you did to make this work? How does one apply the patch? What parameters does one need on the docker run command or docker-compose?

1 Like

My instructions work for those running Plex in a docker container. To make things easier I have deployed my patched version to the Docker Hub registry:

https://hub.docker.com/r/mauimauer/plex
so instead of the official plex container or the linuxserver.io variant you could run mauimauer/plex.
However I have attached a patch in my first post allowing those who want to do so to have insight into the changes I’ve made.

5 Likes

Hi. I can’t get this to work. I have a Ryzen 7 2700U

libva info: VA-API version 1.7.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/radeonsi_drv_video.so
libva info: Found init function __vaDriverInit_1_7
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.7 (libva 2.6.0)
vainfo: Driver version: Mesa Gallium driver 21.1.0-devel for AMD Radeon(TM) Vega 3 Graphics (RAVEN, DRM 3.40.0, 5.10.14-051014-generic, LLVM 11.0.1)
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileHEVCMain10             : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileVP9Profile0            : VAEntrypointVLD
      VAProfileVP9Profile2            : VAEntrypointVLD
      VAProfileNone                   : VAEntrypointVideoProc

this is within Docker. Any suggestions on how I can make this work?

@mauimauer I’m using your docker repository and it’s working great with my Ryzen 2400GE! Any luck with merging the patch back to linuxserver mainline? It’d be great if we could get the regular updates that they push out.

2 Likes

I’m unsure of what permissions are needed on the /dev/dri directory and its contents. Maybe you need to make them writable by non-root users?

I ran chmod -R 777 /dev/dri/ and it didn’t help.

I notice though, outside the container:

crwxrwxrwx  1 root video  226,   0 Feb  8 18:20 card0
crwxrwxrwx  1 root render 226, 128 Feb  8 15:22 renderD128

and inside:

crwxrwxrwx 1 root video         226,   0 Feb 11 17:08 card0
crwxrwxrwx 1 root video2zq7K7E9 226, 128 Feb 11 17:08 renderD128

I wonder if that has anything to do with it?