En este apunte explico cómo conseguir que Tvheadend use las capacidades de transcodificación (encode y decode) por Hardware ofrecidas por Intel Quick Sync Video (por ejemplo en sus NUC’s). Permite que los streams de video utilicen mucho menos ancho de banda. Pensaba que NO me iba a hacer falta debido a mi caso de uso (Tvheadend para ver canales iptv  en un entorno sin problemas de ancho de banda, router Linux + Fibra y clientes raspberry con Kodi por cable Ethernet).

Bueno, pues resulta que sí que necesito transcodificar, tengo dos casos: el primero es cuando uso un cliente Móvil (teléfono, tableta) por la WiFi casera y el segundo si quiero acceder por internet para ver la TV de mi casa (ejemplo: en vacaciones).  Si intento enviar un canal HD (+10Mbps) vía WiFi o Internet a un móvil o una tableta funciona pero con microcortes o retrasos o pérdidas de tráfico, en definitiva inestabilidad.

 

Transcoding

 

Tvheadend soporta transcodificación, tanto software como hardware. La primera es fácil de activar y funciona, pero si le exiges que tenga buena calidad te va a fundir la CPU (100% de consumo) y tendrás microcortes, retrasos, pérdidas de tráfico, inestabilidad. Hay dos opciones 1) transcodificación software sin demasiadas exigencias o 2) transcodificación HW exigiendo buena calidad y mínimo consumo de CPU.

Nota: En mi caso estoy haciendo las pruebas con un NUC D54250WYK, cuenta con CPU Intel Core i5-4250U y GPU (reportada por lspci) Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 09), pero este apunte aplica a cualquier ordenador que use los chips de intel de diferentes generaciones (ojo, algunas pueden no soportar lo que aquí se describe, consulta los enlaces al final de este apunte).

Cómo usar Intel QSV en Linux y en Tvheadend

 

Que Linux use aceleración por HW (QSV): objetivo cumplido

El primer objetivo que me planteé fue que el Linux (gentoo) fuese capaz de acceder al Hardware gráfico (QSV) del Intel NUC. Hay que instalar paquetes estándar (Gentoo en mi caso) y preparar el Kernel. Opcional recomiendo instalar X11 para verificar que se consume QSV en entorno gráfico cuando ves por ejemplo una peli. En cualquier caso también funciona en modo Headless (sin X11), es decir, puedes usar ffmpeg para codificar o de-codificar (transcodificar).

  • Soporte nativo en el Kernel, Sistema Operativo, FFMPEG accediendo a QSV vía VAAPI
    • Ventaja: Funciona.
    • Está documentado en “Soporte nativo de Intel QSV+VAAPI en Linux
    • Nota1: Quick Sync está soportado por el VA API, tanto para encoding como decoding, así ques VAAPI es el método preferido para poder “consumir” dicho Hardware (QSV).
    • Nota2: FFMPEG, uso la nueva 3.1 que ha empezado a soportar VAAPI hace poco tiempo.

 

Que Tvheadend use aceleración por HW (QSV): Work In Progress

Esto es otra historia,  el segundo objetivo consiste en compilar Tvheadend para que acceda al Hardware del Intel NUC (QSV) y sea capaz de usar la aceleración HW. Por desgracia a fecha de Julio de 2016 todavía no es fácil pero se supone que llegará.

Por lo que he podido investigar tenemos dos opciones:

  • Soporte nativo de vaapi en Tvheadend (Solución ideal)

  • Soporte meditante el SDK de Quick Sync de Intel y un Kernel concreto parcheado (no me gusta)

    • Ventaja: Funciona, aunque por lo que he visto no me convence…
    • Desventaja: obliga a usar una Distro+Kernel concretos,
    • Desventaja: Por lo que he visto en los foros es complicado de montar.
    • Desventaja: Condena al NUC a este role específico (tvheadend).
    • He documentado esta opción en la sección “Tvheadend con SDK Quick Sync“.

 

 

Soporte nativo de Intel QSV+VAAPI en Linux (Gentoo)

Lo primero que voy a hacer es preparar el sistema para que funcione Xorg y  la aceleración de video. Te recomiendo que empieces por aquí, aunque no necesites X11 para Tvheadend más tarde, es una forma de quitarme muchas dudas si luego las cosas NO funcionan, es decir prefiero conseguir llegar a la primera “base”, dejar X11 funcionando, comprobar que mi tarjeta i965 funciona correctamente y que se consume por Hardware de forma correcta. Nota: he usado esta fuente https://wiki.gentoo.org/wiki/Intel, https://wiki.gentoo.org/wiki/VAAPI. Mi segunda base será confirmar que incluso sin X11 me funcionan los comandos que comprueban que el hardware GPU es accesible.

  • Configuro VIDEO_CARDS y USE (Habilito el HW decoding H264 y VAAPI)

  • Accept Keywords

  • Licencia fdk-aac

  • USE flags para FFMPEG y para Tvheadend

  • Unmask FFMPEG (para que compile la 3.x)

  • Me aseguro de tener preparado el Kernel según comenta en este enlace https://wiki.gentoo.org/wiki/Intel (yo uso Kernel 4.x)

Rearranco el equipo y continúo.

  • Fuerzo que se recompile todo, con los nuevos flags de USE, las librerías de libva y ffmpeg

  • Compilo Xorg-server

  • Arranco Xorg

  • Desde la CONSOLA X11 ejecuto ‘vainfo’

  • Para probar la aceleración instalo MPV

  • Ejecuto MPV e intento abrir un stream de video. Todo esto en la consola GUI del servidor.

 

Comprobar que FFMPEG consume la GPU con VAAPI

  • Vamos a por la segunda *base*, comprobar que ffmpeg es capaz de realizar una transcodificación delegándoselo a la GPU. Para comprobarlo necesitas instalar una herramienta de intel llamada intel_gpu_tool

  •  A partir de aquí NO necesitamos X11, es decir, trabajamos en modo headless. En mi ejemplo he usado una película ripeada a 1080FullHD con H264 y audio AC3. El objetivo es transcodificarla pero sobre todo que lo haga la GPU. El soporte de VAAPI en FFMPEG se incluyo hace muy poco tiempo.

ffmpegGPUuse

  • Aquí viene la verdadera comprobación, ejecuto intel_gpu_tool en otra sesión de terminal para comprobar que efectivamente se está consumiendo la GPU (Hardware gráfico de Intel QSV)

intel_gpu_toolDeberías ver cómo las barras van indicando el consumo de la GPU, objetivo cumplido. Nuestro Linux es capaz de usar los servicios hardware Quick Sync Video de la tarjeta Intel.

 

Soporte nativo de Intel QSV+VAAPI en Linux (Ubuntu 16.04 LTS)

En esta sección describo cómo he instalado FFMPEG + VAAPI para un Servidor (headless).

Instalación de ffmpeg (fuente: https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu). Otros enlaces de interes: https://gist.github.com/Brainiarc7/95c9338a737aa36d9bb2931bed379219 , https://tvheadend.org/boards/5/topics/22670

PENDIENTE DE TERMINAR !!

 

Tvheadend con soporte nativo VAAPI (Work in Progress)

 

Esta es la sección buena, la opción que queremos que funcione, aunque todavía no lo hace 🙁

El objetivo aquí es sencillo, que Tvheadend incorpore el soporte de forma nativa para acceder a QSV mediante VAAPI directamente, recuerda que QSV – Intel QuickSync Video – permite usar las capacidades Hardware de procesamiento multimedia de la tarjeta fráfica de los procesadores Intel y la clave aquí es cómo acceder a dicho Hardware, en concreto cómo acceder al device driver. El método limpio y sencillo que no requiere tocar el kernel ni usar entornos cerrados de desarrollo es mediante VA API y eso es precisamente lo que necesitamos en Tvheadend, soporte del VA API directo (Video Acceleration API). En FFMPEG ya está hecho, soporta usar VA API, pero… nos falta que Tvheadend lo soporte.

Para conseguirlo es necesario que los desarrolladores de Tvheadend modifiquen el código. Parece que no es demasiado complicado pero obviamente tienen muchas peticiones y tendrán que priorizar. Si tienes un procesador Intel con una tarjeta gráfica embebida de las soportadas te invito a registrarte en Tvheadend y pidas en este hilo #3831 que lo implementen, como todo, cuantos más lo pidan mejor 🙂

Nota: A paritr de aquí y hasta el final de esta sección sobre Tvheadend y VAAPI está “Work in Progress (Julio 2016)“, es decir que iré añadiendo pruebas y documentación…

Nota: FFmpeg puede usar QSV para realizar codificacióndecodificación de múltiples códex en hardware. Para poder usar QSV Tvheadend debe linkarse contra el libmfx dispatcher y este a su vez  se encarga de cargar las librerías de de-codificación (creo que son las libva*). Este dispatcher es un proyecto open source disponible en https://github.com/lu-zero/mfx_dispatch.git.

El soporte de VAAPI en Tvheadend no está completo de momento, usas el pix_fmt incorrecto (esto es sencillo de arreglar) y no configura el dispositivo DRM. Lo dicho, necesita que un desarrollador lo arregle.

Para entender cómo hacer pruebas con esta versión en desarrollo te recomiendo leer la sección siguiente “Compilación manual de Tvheadend” y luego hasta llegar las “Pruebas Agosto 2016” donde describo lo último que estoy probando (una branch especial de ‘lekma’)

Compilación manual de Tvheadend

En esta sección documento cómo estoy compilando Tvheadend “a pelo” desde GitHub, en vez de usar emerge porque me permite ir haciendo pruebas con las distintas liberías (elegir usar las del sistema o las de SDK) y además estar seguro de usar el último código de Tvheadend.

Notar que utilizo  configure con la opción --enable-qsv que provoca que se instalen ffmpeg con las opciones que necesitamos (--enable-libx264 --enable-libx265 --enable-vaapi --enable-libmfx), entre otras.

Como digo, termina y deja el ejecutable en build.linux. El siguiente paso es instalarlo en tu sistema:

En mi caso (ver los argumentos de ./configure) dejo el ejecutable en /usr/bin, es decir en el mismo sitio donde lo deja emerge en Gentoo. Si quieres mantener ambos deberías renombrar uno de los dos o configurar que la versión manual se instale en otro sitio.

Librerías FFMPEG que se Linkan estáticamente al ejecutable

En la compilación manual de Tvheadend estamos creando un ejecutable con muchas librerías linkadas estáticamente dentro del mismo, es decir no utiliza esas librerias de tu sistema operativo sino que compila su propia copia de FFMPEG y sus librerías para linkarlas al ejecutable. No me gusta demasiado, pero la ventaja es que evita conflictos y que podrías tener varias versiones de Tvheadend para hacer pruebas. Estas son las dependencias de FFMpeg que linka estáticamente (fecha Julio 2016):

 

Liberías o paquetes que espera encontrar en el Sistema Operativo

Por otro lado hay una serie de apquetes que espera encontrar en el Sistema Operativo (lo indica durante la ejecución de ./configure)

Y de ellos el más importante es libva

 

Transcodificar por HW

Como comenté al principio de este apunte Tvheadend puede usar libva (vaapi) pero por desgracia luego no funciona. Tras la compilación manual verás múltiples opciones muy interesantes.

TransOptions

Puedo poner la de h264_vaapi, pero …

TransVAAPI

…pero de momento nos da este ERROR

 

Transcodificar por Software (solución temporal)

Tras varias pruebas he conseguido configurar un perfil de transcodificación (software) que funciona bastante bien cuando sólo se usa para un único usuario, un único stream y sobre todo “en casos especiales”, por ejemplo ver la TV desde una tablet cuando no queda más remedio o para verlo conectado por internet. OJo!, es sub-óptimo y como lo fuerces mucho (varios usuarios) te empezará a fallar.

Desde mi punto de vista es una solución TEMPORAL hasta que Tvheadend soporte FFMPEG con VAAPI.

TransSW

A continuación podemos ver un gráfico con el consumo de CPU utilizando la transcodificación Software “veryfast”, 720 bps video y 64bps audio:. Como se puede ver en la parte superior izquierda, la herramienta intel_gpu_tool indica que NO ESTÁ haciendo nada, es decir, funciona todo por Software, como demuestra htop, donde aproximadamente el 25% de los vCores están dedicados a transcodificar.

transSW

El ancho de banda medio consumido es de 750-800Kbps, con ráfaga que llegan a los 2Mbps. En el siguiente gráfico puedes observar en Verde el stream de entrada (un Canal HD) y en Morado el stream de Salida transcodificado.

transbw

 

 

Pruebas Agosto 2016

He descargado el Fork de lekma que según el hilo “Feature #3831: VAAPI Encoding via FFmpeg” tiene una branch (codecs) que podría ser la primera versión que funciona, comentan que ha hecho un trabajo impresionante en la reimplementación del sistema de codecs. Estos son los pasos que he seguido en mi prueba:

Me salvo el antiguo tvheadend añadiendole la versión que tenía compilada:

En un nuevo directorio clono el fork y lo compilo, el proceso es idéntico a lo que describí más arriba.

Importante: cambio al branch “codecs”

Compilo (importante usar –enable-vaapi), y luego instalo.

Me hago una copia del ejecutable antiguo e instalo el nuevo

Hago un backup de la configuración (aunque al arrancar la nueva versión automáticamente haga su propio backup en /etc/tvheadend/backup).

Arranco el log desde otra sesión:

y rearranco tvheadend

Creo 2 nuevos Codec Profiles (nuevo en esta branch, 1xVideo y 1xAudio), creo un nuevo Stream Profile al que asigno los dos Codec Profiles anteriores. He creado un usuario nuevo al que le asigno el Stream Profile y desde un cliente conecto usando este usuario.

Arranco intel_gpu_top y htop en dos terminales y conecto desde el cliente. Resultado de los tests:

Actualizar la versión: Si más adelante van actualizando esta branch, para sincronizar con ella simplemente haz un pull con git y vuelve a compilar

 

 



 

Tvheadend con SDK Quick Sync

He dejado para el final la opción que no me termina de convencer, consiste en usar una distro concreta, con un kernel concreto, instalar el SDK de Intel, parchear el kernel, compilar Tvheadend a mano y en funciona, aunque puede que no en todos los chips de Intel (parece que Skylake es un ejemplo donde NO funciona). Ojo, aunque he conseguido que funcione (la transcodificación por Hardware) veo que sigue consumiendo demasiada CPU y además no consigo que más de un cliente funcionen bien, así que lo dicho, aunque no me convence pero tendré que probarlo más en profundidad algún día.

nuc-d54250wyk-mss

  • Distro.  CentOS 7.1.1503 (sí, es la versión concreta que Intel llama Gold)
  • Entorno de desarrollo. Regístrate como desarrollador al Intel® Media Server Studio – Community Edition, descarga la versión Intel® Media Server Studio for Linux* (199 MB) y copiala a tu Distro (se instala en /opt/intel/mediasdk/lib64/*).
  • Parches del Kernel. Los instalará el SDK de Intel
  • Tvheadend, compilarlo manulamente.

Para probar esta opción voy a crear un Disco con CentOS 7.1.1503 en una USB para no tocar mi instalación en el NUC. Forzaré que haga boot desde dicha USB mientras realizo las pruebas. Nota: Uso USB’s 3.0 o esto sería inmanejable 🙂

Instalo CentOS

  • Requisitos – 2xUSB’s 3.0,
    • USB1: ISO de Instalación de CentOS
    • USB2: Disco destino donde instalaré CentOS
  • Preparo la USB1: ISO de Instalación de CentOS
    • Descargo CentOS 7.1.1503 desde http://mirror.nsc.liu.se/centos-store/7.1.1503/isos/x86_64/
    • Creo una USB Bootable, la inserto en mi iMac.
    • Averiguo el device con ‘df -h’ (resultó ser /dev/disk2)
    • Desmonto el volumen: sudo diskutil unmount /dev/disk2s1
    • Grabo el ISO (notar la ‘r’): dd if=CentOS-7-x86_64-DVD-1503-01.iso of=/dev/rdisk2 bs=4194304
  • Instalación de CentOS
    • Inserto la USB1 en el NUC (CentOS Install Boot)
    • Inserto la USB2 en el NUC (futuro disco destino)
    • Rearranco el NUC y pulso F10 para elegir desde dónde hacer boot (USB1)
    • Arranco con el ISO de instalación de CentOS
      • Selecciono Install CentOS 7
      • Selecciono como Disco Destino la segunda USB2 (reclamo todo su espacio, particiona automático)
      • Hará una instalación mínima
      • Configuro la Red con IP fija
      • Configuro la contraseña de root y creo un usuario luis
      • Cuando termina, pulso Reiniciar, saco la USB1
  • Arranque con USB2 (Donde he instalado CentOS)
    • Al reiniciar pulso F10 para seleccionar la USB2

Instalo SDK Intel Media Server Studio

  • Uso este PDF como guía
    • https://software.intel.com/sites/default/files/media_server_studio_getting_started_guide.pdf
  • Instalo dependencias

  • Verifico que mi HW es compatible

  • Descargo el SDK Media Server Studio
    • Intel® Media Server Studio – Community Edition Version 2016 (Latest Release)     10 Feb 2016
    • https://registrationcenter.intel.com/en/products/
  • NOTA: La IP de mi NUC es 192.168.100.244
    • $ scp MediaServerStudioEssentials2016.tar.gz luis@192.168.100.244:.
  • Vuelvo al NUC como usuario normal (luis)

  • Como “root”

  • Como usuario normal (luis)

  • COMO “root”, compruebo que se han generado los RPM’s del kernel y los instalo:

Rearrancar y comprobar que lo hace con el nuevo kernel

Antes de nada miro en ek Kernel estaba,

Ejemplos del SDK

Nota: Esta sección debería conseguir que puedas instalar los ejemplos para comprobar que la transcodificación por HW funciona. Por desgracia no he conseguido que me funcione, dejo la documentación de todas formas. En mi caso lo ignoré y salté a instalar Tvheadend.

Instalo Tvheadend

Preparo dependencias

  • Añado el usuario “tvheadend”

  • Copio el directorio de configuración.En otro sistema tenía instalado Tvheadend y configurado en /etc/tvheadend, lo que hago es copiarme el directorio de configuración para evitar configurarlo desde cero.

  • DESACTIVO EL FIREWALL DE CENTOS, viene activo por defecto

  • ARRANCO TVHEADEND en un termimal

  • ARRANCO intel_gpu_top en otro terminal

  • ARRANCO htop en otro terminal

centosqsv

  • Pendientes de investigar
    • Nota1: No he aplicado ningún parche tal como se menciona aquí: https://tvheadend.org/issues/3080
    • Nota2: No he aplicado el Fork TheTroll: https://github.com/TheTroll/tvheadend


 

 

 

Enlaces

Enlaces relacionados con este apunte:

Discusiones relevantes en el foro de Tvheadend

Herramientas