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

yeah - I figure I’m just testing until tone mapping can (hopefully) be implemented. But even still, I’m getting bad blocks. I may go down to 390 and see if it makes a difference

Any idea if this will work with the Nvidia Jetson Nano ARM box? That seems like a wicked Plex Server waiting to happen …

1 Like

that looks pretty awesome

but most like it would be CPU and IO limited for anything other than a shield replacement (great client, small server).

it’s not going to replace a dedicated plex server, and probably not replace the majority of x86 based nas devices.

Being a devkit I find it unlikely to be supported, but one can dream :slight_smile:

I think you understood me wrong.

What I meant that right now with HW accel turned on with server setting and the patch to enable NVDEC the situation is as follows:

HEVC transcode:
GPU: Decode --> GPU: Encode

H264 transcode:
CPU: Decode --> GPU: Encode.

I would personally like an H264 transcode to be completely done by the CPU and the GPU the HEVC transcodes. Any idea if this is possible?

In concept, this is possible. You can use the same wrapper script to intercept the encoder selection and tell it to use the non-nvidia encoder. This would take a lot more testing to make sure it is stable as I’m not sure if Plex is passing any parameters that are specific to the encoder. I would recommend you play with it and see how it goes. That particular part is more playing with fire as it can involve changing a lot more than just adding a single parameter like the NVDEC stuff does

Here’s the blockiness I was talking about:

What’s the the source file? 4K? HEVC? 10-bit/HDR?

4K HEVC Main 10 HDR

Nice work on the patch, OP.

rafisher79, I’m suspicious the blocks you are seeing are colors that are getting cut by the conversion of HDR -> SDR. Plex isn’t doing any conversion here, so Plex is simply telling FFMPEG to process as 8-bit even though the source is 10-bit. This causes a hard cut of the colors outside the 8-bit space which I have seen result in washed out colors. I will run through some tests on some 4K HDR media I have here and see if I can recreate the blocky result.

The color issue can be fixed with a tonemap function within FFMPEG, but it also requires some libraries that are not built into the Plex build of FFMPEG. On top of that, the tonemap function currently is software only and limited to a single CPU thread. This means that right now, tonemapping isn’t possible with Plex and if it were it wouldn’t be fast enough to support a live transcode. In order to prevent the color issue, the 4K media needs to have a second “Plex Optimized” copy that has converted the coloring to 8-bit NV12 pixel format.

https://stevens.li/guides/video/converting-hdr-to-sdr-with-ffmpeg/
This is a really good blog post that goes into the what, why, and how to handle this with FFMPEG. I have already tried to do this conversion with Plex, but Plex does not have the zscale filter compiled in currently.

So sadly, for the time being, HDR content (4K and otherwise) on Plex should still remain as direct stream only.

Yeah, I was thinking it could be that, but its weird though - since when I use the CPU decode, it doesn’t have the blocks at all on the very same file.

OK, its definitely a plex issue. I forgot I have emby on that server as well and its not getting the blocks and still using the GPU. Oh well, I guess I’ll just be patient :slight_smile:

As a last request, can you run the movie again, then run ‘ps ax | grep Plex Transcoder2’ so we can see the parameters that were passed to the transcoder?

Sure:

7579 ? Rl 0:17 /usr/lib/plexmediaserver/Plex Transcoder2 -hwaccel nvdec -codec:0 hevc -codec:2 ac3 -ss 5706 -analyzeduration 20000000 -probesize 20000000 -i /media/movies/UHD/Captain America The First Avenger (2011)/Captain America The First Avenger (2011) Remux-2160p.HDR.mkv -filter_complex [0:0]scale=w=2276:h=1280[0];[0]format=pix_fmts=nv12[1] -filter_complex [0:2] aresample=async=1:ocl=‘stereo’:osr=48000[2] -map [1] -metadata:s:0 language=eng -codec:0 h264_nvenc -b:0 68460k -maxrate:0 91280k -bufsize:0 182560k -forced-idr:0 1 -r:0 23.975999999999999 -force_key_frames:0 expr:gte(t,5706+n_forced*1) -map [2] -metadata:s:1 language=eng -codec:1 aac -b:1 256k -f dash -min_seg_duration 1000000 -skip_to_segment 5707 -time_delta 0.0625 -manifest_name http://127.0.0.1:32400/video/:/transcode/session/1k158x17njvjtobysopredmp/a2eaf484-bf00-46e3-8324-59d2a64ffa1f/manifest -avoid_negative_ts disabled -map_metadata -1 -map_chapters -1 dash -start_at_zero -copyts -y -nostats -loglevel quiet -loglevel_plex error -progressurl http://127.0.0.1:32400/video/:/transcode/session/1k158x17njvjtobysopredmp/a2eaf484-bf00-46e3-8324-59d2a64ffa1f/progress
7617 pts/1 S+ 0:00 grep --color=auto Plex Transcoder2

Would it be worthwhile/possible for the script to have a “latest version” check? Checks github, if version = higher, download to same directory, chmod as appropriate, then run latest.

This would be quite useful as updates seem to be coming quite fast with bits here and there (great work by the way, works beautifully)

This is really great, thanks for your time on this!

I have a P2000(418.56) xeon, ubuntu(18.04.2), PMS (1.15.2.793) and I’ve successfully applied your latest patch. H264 MKV files decode with no problems. Here is a partial output from ps ax | grep Plex\ Transcoder2

/usr/lib/plexmediaserver/Plex Transcoder2 -hwaccel nvdec -codec:0 h264

But no H264 MP4 files will use the hardware decoding. Perhaps it has something to do with the #0x01, #0x02 that comes before the codec. I’m not exactly sure what this means. Hopefully it makes more sense to you all. Every file I have tried uses H264 codec.

File1:

/usr/lib/plexmediaserver/Plex Transcoder2 -codec:#0x01 h264

File2:

 /usr/lib/plexmediaserver/Plex Transcoder2 -codec:#0x02 h264 -codec:#0x01

Omatzyo, are there multiple video streams or multiple files for this particular video? I’m not seeing much info on this, but I’m thinking Plex here to trying to merge two videos into a single stream

No, there is only one video with that title, one video stream in the file, and one file only in each of my trials. But I think you’re onto something with the total streams.

Here is a screenshot from one of the MP4 files in subler:
CA

I suppose that the MP4 container can have quite a few streams. And this notation is how plex passes the stream to the transcoder.

In the example above, #0x02 is the video track. The 6 channel audio track is #0x03

/usr/lib/plexmediaserver/Plex Transcoder2 -codec:#0x02 h264 -codec:#0x03 ac3 ...

When I change the player to a different audio track, like stereo, it also changes the parameter sent to the transcoder to #0x01:

/usr/lib/plexmediaserver/Plex Transcoder2 -codec:#0x02 h264 -codec:#0x01 aac ...

Does the wrapper/whitelist that you have setup account for this? Could it account for this?

Thanks for taking a look!

A bit more testing showed that even an MP4 with 2 streams (1 video track and 1 audio track) use the #0x01 and #0x02 notation.

I believe this to be hexadecimal (vs decimal used when an MKV is transcoded) and it seems to be used for all MP4 containers when plex is sending the information to the transcoder.

Finally, simply changing the file extension to MKV does not change the way plex formats the string - i.e. it still uses the hexadecimal format.