Monday, March 26, 2012

Plex Media Server DTS transcoding fix

Plex Media Server 0.9.5.3 unnecessarily transcodes video when transcoding audio for LG clients which can't play DTS. This increases CPU utilization, and it can cause buffering pauses in video if the CPU isn't fast enough. The issue has been in the Plex forums in this thread and others.

This solves the problem. When "Plex Media Server.exe" runs another executable, the attempt is intercepted, and the command line is changed, as described by enachemc on the Plex forum. The command line change tells the transcoder that the device can accept H.264 video at up high profile, 1080p, and level 4.1.

The interception is done using Detours from Microsoft Research. I chose Detours 2.1 because I had problems with Detours 3.0. The code is compiled from PlexTranscodeDetour.c, creating PlexTranscodeDetour.dll. That DLL needs to be inserted into the "Plex Media Server.exe" process. I recommend insertion via withdll-silent.exe. It supports the same switches as the ordinary Detours withdll.exe, but doesn't open a console window. For example, if Plex Media Server is installed in "C:\Program Files\Plex\Plex Media Server" and these files are in "C:\Program Files\Plex\PlexTranscodeDetour", then you can change the Plex Media Server shortcut target to:
"C:\Program Files\Plex\PlexTranscodeDetour\withdll-silent.exe" "/d:C:\Program Files\Plex\PlexTranscodeDetour\PlexTranscodeDetour.dll" "C:\Program Files\Plex\Plex Media Server\Plex Media Server.exe"

I am also including an unmodified withdll.exe, which produces diagnostic output to the console. You only need to try that if you have problems. Alternatively, you could maybe edit "Plex Media Server.exe" to include the DLL via setdll.exe. I don't know if that works.

I recommend using Microsoft compilers such as Visual C++ from Visual Studio Express 2010. Detours does not come with binaries, and if you want to compile it, you must use a Microsoft compiler. You can't even statically link with detours.lib from the GNU toolchain because the linker cannot resolve some of the symbols in detours.lib. If you want to use the GNU toolchain, you can use the instructions I posted earlier to create a detours.dll that you can use. I felt forced to use Visual Studio Express because I didn't think I was allowed to distribute the detours.dll that I created using those instructions.

You can download PlexTranscodeDetour from Dropbox. You are free to do whatever you want with my code here. Detours components are distributed according to the license from Microsoft Research. This code and program comes with absolutely no warranty. Use at your own risk.

6 comments:

smoker said...

first, thanks for the work.

I did exactly as written,
first I closed the running instance of plex, extract the files into the directory, than run the command given as example, plex server starts working.

the result:
I start to play an 1080DTS movie
at start it seems to work,
but after some time the buffering issue come back.

maybe I missed something?

Boris Gjenero said...

You can see if this works because it will reduce CPU usage. On my Q6600, video transcoding uses 99% and audio transcoding uses under 50%.

Unfortunately, there are other problems which this does not address.

Plex uses too much CPU for just streaming the already transcoded temporary files. That's capped at 25% (one core), as if multiple threads aren't allowed to run at the same time to take advantage of multiple cores. I think that's what causes pauses in 720p un-transcoded video with transcoded audio.

That might even be the cause of pauses when transcoding 720p video. It seems Plex transcodes as fast as the CPU will allow and stores the whole video in temporary files. So, 99% CPU usage does not mean that you're at the limits of what your CPU can handle for video transcoding.

PlexTranscoder.exe will transcode some video because it considers the bitrate too high. I think the limit is just over 10 Mbps. I don't know how to change that limit by editing the command line.

The TV is not able to play high bandwidth peaks over the network. For example a tiny fraction of a second peak over 80Mbps or a second of video around 50Mbps is enough to cause buffer underruns. These always happen at the same high motion scenes, regardless of the server software or PC being used. Note that Blu-ray video can have bandwidth peaks. The spec assumes players have a buffer which can handle them. I think the buffer on the TV is too small.

coalfield said...

Thanks for this. I still get the buffering issue, and my CPU usage is not 100% (in fact don't see a noticeable difference). The bit you mentioned about using only 1 core to stream may be the cause, as my quad core AMD X4 610e should me more than capable.

P.s using server: 0.9.6.1

coalfield said...
This comment has been removed by the author.
Unknown said...

Thanks for this solution, but this didn't work for me unfortunately. I have a E2200 CPU overclocked to 3000mhz and using Plex 0.9.6.9.

The CPU stays at 100% all the time while playing 1080DTS movies. Probably my CPU is too slow.

Boris Gjenero said...

There's also a bitrate cap when transcoding, which the current code does not address. Last time I checked it was 10Mbps average bitrate, via one of the "10" parameters in the transcoder command line.

I've given up on Plex for now because even when this works to reduce CPU usage, I still get hesitations after some length of playback. Last time I investigated, it seemed like Plex was running into the limit of 100% of one CPU core when serving transcoded content. I now use Serviio.

When you see 100% CPU usage while transcoding, that doesn't mean your CPU is too slow. Plex transcodes as fast as the CPU will allow and stores that in temporary files. Even if this finishes and CPU usage goes back down, I still get hesitations.