Skip to content

Instantly share code, notes, and snippets.

@bogsen
Last active June 28, 2024 13:46
Show Gist options
  • Save bogsen/37cbad60f6c10cdaddf3b07a56e06147 to your computer and use it in GitHub Desktop.
Save bogsen/37cbad60f6c10cdaddf3b07a56e06147 to your computer and use it in GitHub Desktop.
Fix Plex transcoding HDR videos very slowly when burning subtitles in at the same time

What?

For some reason, although Plex supports hardware-accelerated HDR tone mapping, Plex decides not to use it when subtitles need to be burned in. This results in extremely slow transcoding on hardware that should be able to keep up using hardware acceleration. I've noticed this issue on my server with Intel QuickSync, and this fix is made specifically for that case.

Before the fix, the SW tone mapping was only able to do 6-7 fps on a i5 7400T for an HDR 4K->1080p transcode. With the fix, that same transcode happens with HW tone mapping, and goes up to 82 fps. Even for HDR 4K->4K, this CPU is able to do 35 fps using QuickSync, thus keeping up with at least one video stream.

How do I fix this?

By wrapping "Plex Transcoder" with a script which replaces the software tone mapping with hardware tone mapping.

A filter configuration for software tone mapping looks like this: [0:0]scale=w=1920:h=1080:force_divisible_by=4[0];[0]format=p010,tonemap=mobius[1];[1]format=pix_fmts=nv12[2];[2]inlineass=font_scale=1.000000:font_path=/usr/lib/plexmediaserver/...[3];[3]hwupload[4]

A filter configuration for hardware tone mapping looks like this: [0:0]scale_vaapi=w=1920:h=1080:format=p010[0];[0]hwmap=derive_device=opencl,tonemap_opencl=tonemap=mobius:format=nv12:m=bt709:p=bt709:r=tv,hwdownload[1];[1]format=pix_fmts=nv12[2];[2]inlineass=font_scale=1.000000:font_path=/usr/lib/plexmediaserver/...[3];[3]hwupload[4]

For the linuxserver.io Plex docker image, I've attached a script which can be added into custom-cont-init.d (by using a bind mount) that fixes the issue described here. Use at your own risk, it may cause issues in other transcoding scenarios which I didn't test yet.

#!/bin/bash -ex
cd /usr/lib/plexmediaserver
if [ ! -f "Plex Transcoder.before-hdr-subtitles-fix" ]; then
mv "Plex Transcoder" "Plex Transcoder.before-hdr-subtitles-fix"
fi
cat >"Plex Transcoder" <<"EOF"
#!/usr/bin/env -S perl -l
use warnings;
use strict;
my $found = 0;
for my $arg (@ARGV) {
my $updated = $arg =~ s/(\[[\w:]+\])scale=(w=\d+:h=\d+)[^[]+(\[[\w:]+\]);\3format=p010,tonemap=(\w+)(\[[\w:]+\]);/$1scale_vaapi=$2:format=p010$3;$3hwmap=derive_device=opencl,tonemap_opencl=tonemap=$4:format=nv12:m=bt709:p=bt709:r=tv,hwdownload,format=pix_fmts=nv12$5;/r;
if ($updated ne $arg) {
print("Enabled HW tone mapping:");
print("Original: $arg");
print("Updated: $updated");
$arg = $updated;
$found = 1;
next;
}
$updated = $arg =~ s/(\[[\w:]+\])scale=(w=\d+:h=\d+)[^,[]+/$1hwupload,scale_vaapi=$2,hwdownload/r;
if ($updated ne $arg) {
print("Enabled HW scaling:");
print("Original: $arg");
print("Updated: $updated");
$arg = $updated;
$found = 1;
next;
}
}
if ($found) {
if (!defined $ENV{OCL_ICD_VENDORS}) {
$ENV{OCL_ICD_VENDORS} = '/config/Library/Application Support/Plex Media Server/Cache/cl-icds-linux-x86_64';
$ENV{cl_cache_dir} = '/config/Library/Application Support/Plex Media Server/Cache/Shaders/icr-97-linux-x86_64/';
}
unshift(@ARGV, "-hwaccel_output_format:0", "vaapi");
}
unshift(@ARGV, "/usr/lib/plexmediaserver/Plex Transcoder.before-hdr-subtitles-fix");
exec { $ARGV[0] } @ARGV;
EOF
chmod +x "Plex Transcoder"
@dedsm
Copy link

dedsm commented Feb 27, 2024

direct path in a privileged container, but this is not changing configuration at all, so if you already have hw transcoding working without the patch, it should work with it, maybe check that the paths are correct?

@vlitkowski
Copy link

vlitkowski commented Feb 27, 2024

direct path in a privileged container, but this is not changing configuration at all, so if you already have hw transcoding working without the patch, it should work with it, maybe check that the paths are correct?

path are the same as yours, and HW transcoding with tonemapping is working

following my intel drivers versions
libva info: VA-API version 1.14.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_14
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.14 (libva 2.12.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 22.3.1 ()

Kernel is 6.2.16-19-pve

what is your version of proxmox and kernel ?

@JshGrn
Copy link

JshGrn commented Feb 27, 2024

Is this transcoding subtitles without HDR->SDR?

@vlitkowski
Copy link

4] Impossible to convert between the formats supported by the filter 'graph 0 input from stream 0:0' and the filter 'auto_scale_0'
Feb 28, 2024 10:42:01.240 [124051206925112] ERROR - [Req#f2e/Transcode/otac9tmocqr6coslhhxpvrhw/229ea302-6ab6-4989-8047-cbcd2e381764] Error reinitializing filters!
Feb 28, 2024 10:42:01.240 [124051295927096] ERROR - [Req#f2f/Transcode/otac9tmocqr6coslhhxpvrhw/229ea302-6ab6-4989-8047-cbcd2e381764] Failed to inject frame into filter network: Function not implemented
Feb 28, 2024 10:42:01.240 [124051273042744] ERROR - [Req#f30/Transcode/otac9tmocqr6coslhhxpvrhw/229ea302-6ab6-4989-8047-cbcd2e381764] Error while processing the decoded data for stream #0:0
Feb 28, 2024 10:42:01.558 [124051213253432] ERROR - [Req#f51/Transcode/otac9tmocqr6coslhhxpvrhw/229ea302-6ab6-4989-8047-cbcd2e381764] Impossible to convert between the formats supported by the filter 'Parsed_overlay_1' and the filter 'auto_scale_1'
Feb 28, 2024 10:42:01.558 [124051198487352] ERROR - [Req#f52/Transcode/otac9tmocqr6coslhhxpvrhw/229ea302-6ab6-4989-8047-cbcd2e381764] Error reinitializing filters!
Feb 28, 2024 10:42:01.559 [124051206925112] ERROR - [Req#f53/Transcode/otac9tmocqr6coslhhxpvrhw/229ea302-6ab6-4989-8047-cbcd2e381764] Failed to inject frame into filter network: Function not implemented
Feb 28, 2024 10:42:01.559 [124051295927096] ERROR - [Req#f54/Transcode/otac9tmocqr6coslhhxpvrhw/229ea302-6ab6-4989-8047-cbcd2e381764] Error while processing the decoded data for stream #0:0

@dedsm
Copy link

dedsm commented Feb 28, 2024

@vlitkowski I'm guessing the source format is something that the hardware transcoder doesn't support, does it happen with all the videos?

my vainfo:

libva info: VA-API version 1.14.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_14
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.14 (libva 2.12.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 22.3.1 ()
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            :	VAEntrypointVLD
      VAProfileMPEG2Main              :	VAEntrypointVLD
      VAProfileH264Main               :	VAEntrypointVLD
      VAProfileH264Main               :	VAEntrypointEncSliceLP
      VAProfileH264High               :	VAEntrypointVLD
      VAProfileH264High               :	VAEntrypointEncSliceLP
      VAProfileJPEGBaseline           :	VAEntrypointVLD
      VAProfileJPEGBaseline           :	VAEntrypointEncPicture
      VAProfileH264ConstrainedBaseline:	VAEntrypointVLD
      VAProfileH264ConstrainedBaseline:	VAEntrypointEncSliceLP
      VAProfileVP8Version0_3          :	VAEntrypointVLD
      VAProfileHEVCMain               :	VAEntrypointVLD
      VAProfileHEVCMain10             :	VAEntrypointVLD
      VAProfileVP9Profile0            :	VAEntrypointVLD
      VAProfileVP9Profile2            :	VAEntrypointVLD

and my kernel is newer: 6.5.11-8-pve

@vlitkowski
Copy link

vlitkowski commented Feb 28, 2024

@vlitkowski I'm guessing the source format is something that the hardware transcoder doesn't support, does it happen with all the videos?

my vainfo:

libva info: VA-API version 1.14.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_14
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.14 (libva 2.12.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 22.3.1 ()
vainfo: Supported profile and entrypoints
      VAProfileMPEG2Simple            :	VAEntrypointVLD
      VAProfileMPEG2Main              :	VAEntrypointVLD
      VAProfileH264Main               :	VAEntrypointVLD
      VAProfileH264Main               :	VAEntrypointEncSliceLP
      VAProfileH264High               :	VAEntrypointVLD
      VAProfileH264High               :	VAEntrypointEncSliceLP
      VAProfileJPEGBaseline           :	VAEntrypointVLD
      VAProfileJPEGBaseline           :	VAEntrypointEncPicture
      VAProfileH264ConstrainedBaseline:	VAEntrypointVLD
      VAProfileH264ConstrainedBaseline:	VAEntrypointEncSliceLP
      VAProfileVP8Version0_3          :	VAEntrypointVLD
      VAProfileHEVCMain               :	VAEntrypointVLD
      VAProfileHEVCMain10             :	VAEntrypointVLD
      VAProfileVP9Profile0            :	VAEntrypointVLD
      VAProfileVP9Profile2            :	VAEntrypointVLD

and my kernel is newer: 6.5.11-8-pve

thanks for your feeback
I've the same issues with all videos 4K HDR videos as soon has i select PGS subtitles
can you share me your grub config ?

@dedsm
Copy link

dedsm commented Feb 28, 2024

I think the issue is the PGS subtitles, I don't think that will work, SRT is your friend

@vlitkowski
Copy link

vlitkowski commented Feb 28, 2024

I think the issue is the PGS subtitles, I don't think that will work, SRT is your friend

SRT is working without this fix

@su-thomas
Copy link

I just wanted to let you guys know that one of my first tasks for the newyear is going to be to overhaul subtitle burn in, to not only include a similar change to this (but for more than just linux) but hw assisted burn in for image based subtitle formats such as pgs. Keep an eye out for a preview build in the plex forums in jan or feb.

hey @chrisdecker08 any updates on this? Really looking forward to Plex having this functionality, its one of the things Jellyfin does much better currently.

@JshGrn
Copy link

JshGrn commented Jun 25, 2024

I have kind of given up on it, I think they have different priorities.

@chrisdecker08
Copy link

I am about 80% done with this, however higher priority issues keep popping up :P. Most notably I am constantly playing whack a mole fixing tone mapping on linux for intel devices.

@JshGrn
Copy link

JshGrn commented Jun 26, 2024

Can Plex not introduce some kind of pool where people donate to a specific task? I would vote with my money to prioritise this feature over any mapping fixes personally.

@Drakonas
Copy link

Drakonas commented Jun 28, 2024

Can Plex not introduce some kind of pool where people donate to a specific task? I would vote with my money to prioritise this feature over any mapping fixes personally.

I wanted to put some perspective on why Plex had to change priorities as some may not be aware.

Linux kernel 6.8 broke HDR tonemapping for Intel encoding accidentally. And this bug was shipped with ubuntu 24.04 LTS release and won't have the fix until 24.04.1 in probably 6 months to a year. Non-LTS releases can update to the fixed kernel already, but LTS channel is stuck with it.

This sent everyone in a panic, because it means everyone was updating and unable to use Plex HDR content without issues.

Sadly, it makes sense that Plex has to change priorities... The subtitle burnin can be avoided by turning off subtitles or using non-image based subtitles like srt. There are many ways around that issue.

Many paying customers could not get around their vm hosts with Intel hardware being unable to display tonemapped content.

Unfortunately, it's a better business decision to fix the issue users can't work around first, especially when they know there's not going to be a fix by Ubuntu for months.

@JshGrn
Copy link

JshGrn commented Jun 28, 2024

I am fully aware that it is a priority and understand it, but my suggestion is relating to perhaps Plex having a feature 'vote' where people could pool towards a target feature which would then allow for additional development for that said feature.

People do it on here quite often with large repos that are depended on for lots of people. I personally would put £100 GBP towards this, which may on its own be nothing but if a pool of other people that want to stay with Plex put together it should add up to enough for Plex to warrant additional development on the feature. (and others moving forward).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment