Linux HOW-TO: Get Kodi to hardware decode HEVC 10bit files on NVIDIA GFX cards
#1
DISCLAIMER - This is just what works for me, with my hardware - YMMV!

This has been tested on Ubuntu 20.04.3 with kernel 5.4.0-91-generic.  GFX - NVidia GT 1030 with driver version 470.86
Note that Kodi itself can use this card for 8bit hevc decoding via VDPAU, just not 10bit.

Kodi cannot hardware decode HEVC 10bit files with it's current VDPAU implementation and that's unlikely to change.  Therefore I decided to take another approach and use an external player that can hardware decode them (https://mpv.io/).

For Ubuntu this can be installed with sudo apt install mpv. The Ubuntu package installs a mpv.conf file in /etc/mpv which globally enables hardware decoding using vaapi, and should be changed really (see mpv documentation here) although we will be over-riding it anyway.

You can see which hardware decoders mpv can use for hevc by issuing mpv --hwdec=help | grep hevc in a terminal.  You can also start mpv playing a file by issuing mpv /path/to/hevc/video.mkv and press [ctrl]+h to enable hardware decoding.  Mpv will display which decoder it is using.  In my case, it's nvdec-copy.   Copy means it copies back to system ram which does add a little cpu usage, but is still far better than total software decoding.

Once mpv is installed, we need to trigger it from Kodi using playercorefactory.xml.  This is how mine looks.

xml:
<playercorefactory>
  <players>
    <player name="MPV" type="ExternalPlayer" audio="false" video="true">
      <filename>/home/xbmc/scripts/exec-mpv.sh</filename>
      <args>"{1}"</args>
      <hidexbmc>false</hidexbmc>
    </player>
  </players>
  <rules action="prepend">
    <rule name="10bit" filename=".*10bit*." player="MPV"/>
  </rules>
</playercorefactory>

This executes the exec-mpv.sh shell script for any video file that contains 10bit in the full file path.  The script basically contains the full command line for launching mpv correctly and mine is listed below.

xml:
set -o noglob
set -f
export DISPLAY=:1.1
/usr/bin/mpv --fs=yes --hwdec=nvdec-copy --vo=gpu --no-sub --audio-device=alsa/plughw:CARD=NVidia,DEV=7 --audio-channels=7.1,5.1,stereo --volume=100 --input-ipc-server=/tmp/mpvsocket "$1"

The first two set options stop the shell from doing any filename expansion so that the correct full path from Kodi is passed to mpv.
export DISPLAY is there because Kodi is running in a different XScreen to my desktop, but on the same PC and I want to start mpv on the same XScreen as Kodi.  If you only have one TV/Monitor, then you don't need it.

The next bits of the command line break down as follows;
 
  • --fs=yes - start in full screen
  • --hwdec=nvdec-copy - use the hardware decoder we determined earlier by running mpv and pressing [ctrl]+c
  • --vo=gpu - output video to the gpu.  This is required (see the docs)
  • --no-sub - don't show any subtitles
  • --audio-device=alsa/plughw:CARD=NVidia,DEV=7 - where to output the audio (see below)
  • --audio-channels=7.1,5.1,stereo - what audio arrangements we can use
  • --volume=100 - obvious, but needed for proper passthrough audio
  • --input-ipc-server=/tmp/mpvsocket - needed for remote control (see below) not needed if you are using a keyboard or mouse
  • "$1" - contains the full path and filename from Kodi


To find the audio output, I first looked in Kodi to see what it is outputting to (no pulseaudio here because I want trueHD etc!).  For me, it says HDA Nvidia, ONK TX-SR508 on HDMI #1.  The important bits here are HDA Nvidia and HDMI#1.  If you execute mpv --audio-device=help in a terminal, mpv will display all the audio sinks it can see.  What you want to find is the one that is labelled as the same output that Kodi is using (in my case HDA Nvidia, hdmi 1) and says "hardware device with all software conversions" after it.  The start of that line, the bit between the single quotes, is the bit you need to use for your audio device.

EG for me, mpv lists 'alsa/plughw:CARD=NVidia,DEV=7' (HDA NVidia, HDMI 1/Hardware device with all software conversions).  The bit in brackets matches Kodi's audio output and the bit in between the single quotes goes into the --audio-device.

Once you have created your script and playercorefactory files, restart Kodi and play one of your 10bit files (remembering it has to have 10bit in there somewhere in the path/filename) and see if it works!

At this point you might notice that mpv does not change your TV's refresh rate like Kodi does.  To fix this, install this mpv plugin which uses Xrandr to switch refresh rates.  Installation instructions are contained within the link.

If you are using a keyboard/mouse to control Kodi then that's it done.  If however you use a remote like me then you might want to be able to control mpv with it also.  I don't use ir-keytable so if you do, you're on your own!  I do use lirc though and the easiest way to control mpv is by using irexec.

The following is an excerpt from my irexec file and controls mpv by sending simple keypresses to it - this is enough for my needs but could easily be expanded to toggle subtitles for instance. You will need socat installed if it isn't already.  It simply sends commands to the socket we created with --input-ipc-server=/tmp/mpvsocket.  You will need to (re)start irexec to get it to read the new config file.  Yes, I forgot to do that! Blush

cpp:
begin
  prog = irexec
  remote = onkyo
  button = KEY_C
  config = echo '{"command":["keypress","i"]}' | socat - /tmp/mpvsocket
end

begin
  prog = irexec
  remote = onkyo
  button = KEY_PLAY
  config = echo '{"command":["keypress","p"]}' | socat - /tmp/mpvsocket
end

begin
  prog = irexec
  remote = onkyo
  button = KEY_RIGHT
  config = echo '{"command":["keypress","PGDWN"]}' | socat - /tmp/mpvsocket
end

begin
  prog = irexec
  remote = onkyo
  button = KEY_LEFT
  config = echo '{"command":["keypress","PGUP"]}' | socat - /tmp/mpvsocket
end

begin
  prog = irexec
  remote = onkyo
  button = KEY_ENTER
  config = echo '{"command":["keypress","O"]}' | socat - /tmp/mpvsocket
end

begin
  prog = irexec
  remote = onkyo
  button = KEY_STOP
  config = echo '{"command":["keypress","q"]}' | socat - /tmp/mpvsocket
end

And that's it!  Hopefully this might help someone other than me, but if not, it's a handy reference I can come back to in the future.

Finally, I would like to see Kodi be able to do this itself, either by extending the current VDPAU interface or having a new NVDEC interface.  Sadly, at this point, my skills are nowhere near being able to do this but I'll keep reading and maybe one day eh?
Learning Linux the hard way !!
Reply

Logout Mark Read Team Forum Stats Members Help
HOW-TO: Get Kodi to hardware decode HEVC 10bit files on NVIDIA GFX cards0