Skip to main content

Ubuntu에서 QSV (-hwaccel qsv)를 쓸 수 있게 ffmpeg를 빌드하는 방법

일러두기

본 글은 원글을 참조 번역하며, 실제로 막힌 부분에 대한 수정이 이뤄져 있습니다.

Debian에서 QSV로 빠르게 인코딩하고 싶다!

이 글에서는 ffmpeg -hwaccel vaapi (VAAPI + i965) 보다 높은 스루풋/고품질을 얻을 수 있는 ffmpeg -hwaccel qsv (libmfx + iHD)를 쓸 수 있는 ffmpeg 빌드를 Ubuntu에서 하게 됩니다.

구성

소프트웨어

Ubuntu는 2020년 4월 1일 버전으로 설치되어 있습니다. 아쉽게도 LTS인 Groovy가 아닌데, 18년도랑 20년도의 버전 차이가 상당히 큰 점, 설치 당시에 아직 LTS가 나오지 않은 점 탓에 조금 애매한 버전이 깔려 있습니다. 하지만 웬만한 라이브러리 수급에 큰 문제는 없기 때문에 이대로 진행하려고 합니다.

$ lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.1 LTS
Release: 20.04
Codename: focal

하드웨어

Intel Quick Sync Video (libmfx + iHD)를 사용한 하드웨어 인코딩/디코딩을 위해서는, Core i 시리즈로는 제 6세대 이상이 필요합니다. 다행히도 제 노트북은 아슬아슬하게 이 조건을 충족하기 때문에 그대로 진행하고자 합니다.

CPU별 자세한 기능 지원 사항은 https://trac.ffmpeg.org/wiki/Hardware/QuickSync에서 자세하게 확인할 수 있습니다.

하드웨어 종별명칭비고
CPUIntel(R) Core(TM) i5-6200 CPU @ 2.30GHzSky Lake
Memory8GBOnboard

설치 방법

빌드 도구 설치

#빌드에 공통으로 사용할 패키지를 설치
$ sudo apt install build-essential git cmake pkg-config

libva (VA-API) 빌드, 설치, 동작 확인

#의존하는 패키지의 설치
$ sudo apt install meson libdrm-dev automake libtool

#LibVA 최신판 다운로드
$ git clone https://github.com/intel/libva.git
$ cd libva

# 빌드 및 설치
$ ./autogen.sh
$ make
$ sudo make install
...(중략)
Libraries have been installed in:
   /usr/local/lib

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the 'LD_RUN_PATH' environment variable
     during linking
   - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to '/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.

libva가 설치된 /usr/local/lib는 LD-PATH에 포함되어 있지 않으므로, 아래의 명령을 통해 추가해야 합니다.

이걸 함으로써 libva2 패키지(버전 2.10.0)이 /usr/lib에 설치되어 있어도, 이번 설치한 최신판이 우선되어 선택되게 됩니다.

sudo sh -c "echo /usr/local/lib >> /etc/ld.so.conf.d/local.conf"
sudo ldconfig

ldconfig가 작동하는지 확인합니다. vainfo에서 참조하고 있는 libva가 /usr/local/lib를 가리키고 있는 것을 알 수 있습니다.

# vainfo 패키지 설치
$ sudo apt install vainfo
# vainfo가 참조하고 있는 libva가 조금 전 빌드한 것임을 확인
$ ldd /usr/bin/vainfo | grep /usr/local/
        libva-drm.so.2 => /usr/local/lib/libva-drm.so.2 (0x00007fe6f8bc4000)
        libva.so.2 => /usr/local/lib/libva.so.2 (0x00007fe6f8b95000)

참고로 vainfo는 Video Accelerate Info로 VA-API의 현재 설치 상황을 확인할 수 있습니다.

또 VA-API 드라이버가 설치 되어 있지 않아서 드라이버가 열리지 않으면 에러가 표시됩니다.

# vainfo를 사용해도 드라이버가 없으면 에러가 난다
$ vainfo
error: can't connect to X server!
libva info: VA-API version 1.8.0
libva info: Trying to open /usr/local/lib/dri/iHD_drv_video.so
libva info: va_openDriver() returns -1
libva info: Trying to open /usr/local/lib/dri/i965_drv_video.so
libva info: va_openDriver() returns -1
vaInitialize failed with error code -1 (unknown libva error),exit

Ubuntu Server 같이 원래 디스플레이가 없는 경우 X server에 연결할 수 없다는 오류가 나타나는 건 자연스럽습니다. 실제로 그런 장치에서 해보질 않아서 그 문제 자체를 무시할 수 있는지는 확인하지 못했습니다.

VA-API 드라이버 (iHD_drv_video.so)의 빌드와 설치

이제 iHD_drv_video.so를 빌드합니다.

#의존 패키지의 설치
sudo apt install libpciaccess-dev

#의존 라이브러리(Intel(R) Graphics Memory Management Library) 빌드
$ cd
$ git clone https://github.com/intel/gmmlib
$ cd gmmlib/
$ mkdir build && cd build
$ cmake ..
$ make

#VA-API 드라이버(iHD_drv_video.so) 빌드
$ cd
$ git clone https://github.com/intel/media-driver
$ mkdir build_media
$ cd build_media/
$ cmake ../media-driver
$ make
$ sudo make install

여기까지 오면 vainfo 명령에서 새로운 드라이버가 인식됩니다.

# vainfoを実行
$ sudo vainfo
error: can't connect to X server!
libva info: VA-API version 1.8.0
libva info: Trying to open /usr/local/lib/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_8
libva info: va_openDriver() returns 0
vainfo: VA-API version: 1.8 (libva 2.4.0)
vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 20.2.pre (3640b64c)
vainfo: Supported profile and entrypoints
      VAProfileNone                   : VAEntrypointVideoProc
      VAProfileNone                   : VAEntrypointStats
      VAProfileMPEG2Simple            : VAEntrypointVLD
      VAProfileMPEG2Simple            : VAEntrypointEncSlice
      VAProfileMPEG2Main              : VAEntrypointVLD
      VAProfileMPEG2Main              : VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointVLD
      VAProfileH264Main               : VAEntrypointEncSlice
      VAProfileH264Main               : VAEntrypointFEI
      VAProfileH264Main               : VAEntrypointEncSliceLP
      VAProfileH264High               : VAEntrypointVLD
      VAProfileH264High               : VAEntrypointEncSlice
      VAProfileH264High               : VAEntrypointFEI
      VAProfileH264High               : VAEntrypointEncSliceLP
      VAProfileVC1Simple              : VAEntrypointVLD
      VAProfileVC1Main                : VAEntrypointVLD
      VAProfileVC1Advanced            : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointVLD
      VAProfileJPEGBaseline           : VAEntrypointEncPicture
      VAProfileH264ConstrainedBaseline: VAEntrypointVLD
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSlice
      VAProfileH264ConstrainedBaseline: VAEntrypointFEI
      VAProfileH264ConstrainedBaseline: VAEntrypointEncSliceLP
      VAProfileVP8Version0_3          : VAEntrypointVLD
      VAProfileVP8Version0_3          : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointVLD
      VAProfileHEVCMain               : VAEntrypointEncSlice
      VAProfileHEVCMain               : VAEntrypointFEI
      VAProfileHEVCMain10             : VAEntrypointVLD
      VAProfileHEVCMain10             : VAEntrypointEncSlice
      VAProfileVP9Profile0            : VAEntrypointVLD
      VAProfileVP9Profile2            : VAEntrypointVLD```

이상으로 하드웨어 가속이 준비 완료되었습니다. Media SDK에서 필요한 VA-API(libva)의 최신판 드라이버 도입을 끝냈습니다.

Media SDK의 빌드, 설치

git에서 Media SDK를 다운로드, 빌드, 설치합니다.

빌드 플래그 및 설치 위치는 스크립트를 확인하면 알 수 있습니다.

 git에서 MediaSDK 다운로드
$ git clone https://github.com/Intel-Media-SDK/MediaSDK msdk
$ cd msdk

# 빌드 디렉토리 작성
$ mkdir build && cd build

# cmake 실행, 빌드 플래그가 마지막에 표시
$ cmake ..
...(略)...
Release flags:
  CMAKE_C_FLAGS_RELEASE                   : -O3 -DNDEBUG
  CMAKE_CXX_FLAGS_RELEASE                 : -O3 -DNDEBUG
Debug flags:
  CMAKE_C_FLAGS_DEBUG                     : -g -D_DEBUG
  CMAKE_CXX_FLAGS_DEBUG                   : -g -D_DEBUG
Install:
  CMAKE_INSTALL_PREFIX                    : /opt/intel/mediasdk
  CMAKE_INSTALL_FULL_INCLUDEDIR           : /opt/intel/mediasdk/include
  CMAKE_INSTALL_FULL_LIBDIR               : /opt/intel/mediasdk/lib
  CMAKE_INSTALL_FULL_DATADIR              : /opt/intel/mediasdk/share
Enable:
  ENABLE_OPENCL                           : ON
  ENABLE_X11                              : OFF
  ENABLE_X11_DRI3                         : OFF
  ENABLE_WAYLAND                          : OFF
  ENABLE_ITT                              : OFF
  ENABLE_TEXTLOG                          : OFF
  ENABLE_STAT                             : OFF
Build:
  BUILD_RUNTIME                           : ON
  BUILD_DISPATCHER                        : ON
  BUILD_SAMPLES                           : ON
  BUILD_TUTORIALS                         : ON
  BUILD_TESTS                             : OFF
  BUILD_TOOLS                             : OFF
  BUILD_KERNELS                           : OFF
...(略)...


# make & make install. 설치 장소를 확인.
$ make
$ sudo make install
...(중략)...
-- Install configuration: "release"
-- Installing: /opt/intel/mediasdk/share/mfx/plugins.cfg
-- Installing: /opt/intel/mediasdk/lib/libmfx.so.1.32
-- Installing: /opt/intel/mediasdk/lib/libmfx.so.1
-- Installing: /opt/intel/mediasdk/lib/libmfx.so
-- Installing: /opt/intel/mediasdk/lib/pkgconfig/libmfx.pc
-- Installing: /opt/intel/mediasdk/include/mfx
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvideo++.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxpcp.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvstructures.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxcommon.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxla.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxastructures.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxplugin.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxscd.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxaudio++.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxpak.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxaudio.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxadapter.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxdefs.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxplugin++.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvp8.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvideo.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxjpeg.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxfeihevc.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxsession.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxfei.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxdispatcherprefixedfunctions.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxvp9.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxstructures.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxbrc.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxenc.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxcamera.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxsc.h
-- Installing: /opt/intel/mediasdk/include/mfx/mfxmvc.h
-- Installing: /opt/intel/mediasdk/lib/pkgconfig/mfx.pc
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_decode
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_encode
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_fei
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_hevc_fei
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_hevc_fei_abr
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_vpp
-- Installing: /opt/intel/mediasdk/share/mfx/samples/sample_multi_transcode
-- Installing: /opt/intel/mediasdk/share/mfx/samples/libsample_rotate_plugin.so
-- Installing: /opt/intel/mediasdk/share/mfx/samples/libvpp_plugin.a
-- Installing: /opt/intel/mediasdk/share/mfx/samples/libcttmetrics.so
-- Installing: /opt/intel/mediasdk/share/mfx/samples/metrics_monitor
-- Installing: /opt/intel/mediasdk/lib/libmfxhw64.so.1.32
-- Installing: /opt/intel/mediasdk/lib/libmfxhw64.so.1
-- Installing: /opt/intel/mediasdk/lib/libmfxhw64.so
-- Installing: /opt/intel/mediasdk/lib/pkgconfig/libmfxhw64.pc
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_hevce_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_hevc_fei_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_vp9e_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_h264la_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_hevcd_hw64.so
-- Up-to-date: /opt/intel/mediasdk/lib/mfx/libmfx_hevcd_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_vp8d_hw64.so
-- Installing: /opt/intel/mediasdk/lib/mfx/libmfx_vp9d_hw64.so

$ cd 

MediaSDK가 설치된 /opt/intel/mediasdk/libLD-PATH에 포함되어 있지 않으므로, 아래 명령으로 추가합니다.

$ sudo sh -c "echo /opt/intel/mediasdk/lib/ >> /etc/ld.so.conf.d/mediasdk.conf"
$ sudo ldconfig

참고로 ldconfig는 상당히 유용한데, lib를 새로 저장한 경우, 시스템이 인식하도록 새로고쳐주는 명령입니다. 이걸 하지 않고 빌드를 진행하면 올바르게 lib를 읽어들이지 못할 수 있습니다.

ffmpeg 빌드

이제 ffmpeg를 빌드합니다.

#libfdk-aac를 위해선 non-free 저장소를 추가해야 합니다...만 Ubuntu에서는 제대로 작동하지 않았는데 별 문제가 없었습니다.
$ sudo apt install software-properties-common
$ sudo apt-add-repository non-free

# 의존 패키지 설치
$ sudo apt update -qq && sudo apt -y install \
   autoconf \
   automake \
   build-essential \
   cmake \
   git-core \
   libass-dev \
   libfreetype6-dev \
   libgnutls28-dev \
   libsdl2-dev \
   libtool \
   libva-dev \
   libvdpau-dev \
   libvorbis-dev \
   libxcb1-dev \
   libxcb-shm0-dev \
   libxcb-xfixes0-dev \
   pkg-config \
   texinfo \
   wget \
   yasm \
   zlib1g-dev \
   nasm \
   libx264-dev \
   libx265-dev libnuma-dev \
   libvpx-dev \
   libfdk-aac-dev \
   libmp3lame-dev \
   libopus-dev \
   libaom-dev

# Ubuntu에서 $PKG_CONFIG_PATH가 기존에 공란이었기에, 기본값을 찾아서 추가해야 했습니다. /usr/local/lib/를 추가하여 문제를 해결했습니다. $ echo $PKG_CONFIG_PATH를 해서 값이 공란이라면 아래 내용을 추가해보세요.
$ export PKG_CONFIG_PATH=/usr/local/lib

# mediasdk의 lib와 include 위치를 표시하는 pkgconfig가 비표준 장소에 있으므로
# 이대로면 Configure 단계에서 위치 지정이 불가합니다. 환경 변수로 참조를 추가합니다.
$ export PKG_CONFIG_PATH=/opt/intel/mediasdk/lib/pkgconfig:$PKG_CONFIG_PATH

# ffmpeg 소스를 다운로드하여 빌드, 설치
$ cd 
$ wget -O ffmpeg-snapshot.tar.bz2 https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2
$ tar xjvf ffmpeg-snapshot.tar.bz2
$ cd ffmpeg
$ ./configure \
  --extra-libs="-lpthread -lm" \
  --enable-libmfx \
  --enable-gpl \
  --enable-gnutls \
  --enable-libaom \
  --enable-libass \
  --enable-libfdk-aac \
  --enable-libfreetype \
  --enable-libmp3lame \
  --enable-libopus \
  --enable-libvorbis \
  --enable-libvpx \
  --enable-libx264 \
  --enable-libx265 \
  --enable-nonfree
$ make
$ sudo make install

이로써 ffmpeg의 설치가 완료되었습니다.

문제 해결

설치가 다 끝났는데, libx264.so.146과 같은 파일을 요구하며 아무것도 진행되지 않을 수 있습니다.

동작 테스트

설치한 ffmpeg의 확인

빌드한 libmfx를 참조하고 있는 것을 확인합니다.

또, 인코더, 디코더 일람을 표시하고 QSV 대응 코덱이 목록에 있는 것을 확인합니다.

# mediasdk를 참조하고 있는 것을 확인
[email protected]:~$ ldd /usr/local/bin/ffmpeg | grep /opt
        libmfx.so.1 => /opt/intel/mediasdk/lib/libmfx.so.1 (0x00007f44af339000)

# QSV를 사용한 디코더가 목록에 있는 것을 확인
$  ffmpeg -decoders|grep qsv
 V....D h264_qsv             H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration) (codec h264)
 V....D hevc_qsv             HEVC (Intel Quick Sync Video acceleration) (codec hevc)
 V....D mjpeg_qsv            MJPEG video (Intel Quick Sync Video acceleration) (codec mjpeg)
 V....D mpeg2_qsv            MPEG-2 video (Intel Quick Sync Video acceleration) (codec mpeg2video)
 V....D vc1_qsv              VC-1 video (Intel Quick Sync Video acceleration) (codec vc1)
 V....D vp8_qsv              VP8 video (Intel Quick Sync Video acceleration) (codec vp8)
 V....D vp9_qsv              VP9 video (Intel Quick Sync Video acceleration) (codec vp9)

# QSV를 사용한 인코더가 목록에 있는 것을 확인
$  ffmpeg -encoders|grep qsv
 V..... h264_qsv             H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration) (codec h264)
 V..... hevc_qsv             HEVC (Intel Quick Sync Video acceleration) (codec hevc)
 V..... mjpeg_qsv            MJPEG (Intel Quick Sync Video acceleration) (codec mjpeg)
 V..... mpeg2_qsv            MPEG-2 video (Intel Quick Sync Video acceleration) (codec mpeg2video)
 V..... vp9_qsv              VP9 video (Intel Quick Sync Video acceleration) (codec vp9)

살짝 인코딩을 해본 결과

자세한 내용은 아직

이 부분은 저도 직접 테스트를 해보고 첨부하도록 하겠습니다. 간략하게 EPGStation에서 테스트해본 결과 라이브가 아닌 파일은 실시간 전송이 가능할 정도였으며 배속도 CPU에 비해 상당히 빠르게 진행된 것을 체감할 수 있었습니다.

병렬 다수 파일 인코딩도 가능

시스템 부하를 확인

바깥 링크

원문 제공 링크

Build Media SDK on Ubuntu (Intel-Media-SDK)

https://github.com/Intel-Media-SDK/MediaSDK/wiki/Build-Media-SDK-on-Ubuntu

링크 본문에서 변경점 (=현 블로그의 글과 이 링크의 글이 더 유사합니다)

  1. LD_LIBRARY_PATH에 /usr/local/lib를 추가하는 순서가 포함되어 있습니다.
  2. LD_LIBRARY_PATH에 /opt/intel/mediasdk/lib/를 추가하는 순서가 포함되어 있습니다.

Compile FFmpeg for Ubuntu, Debian, or Mint

https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu

링크 본문에서 변경점

  1. 빌드 할 때 폴더를 더 단순하게 사용하고 있습니다.
  2. QSV 대응을 위해 --enable-libxmf 를 추가하였습니다.
  3. liboam은 소스에서 빌드하지 않고 패키지를 사용하였습니다.
  4. gnutls 패키지가 --pkg-config-flags="--static"를 지원하지 않으므로 --pkg-config-flags="--static"를 삭제합니다.

Hardware/QuickSync – FFmpeg

https://trac.ffmpeg.org/wiki/Hardware/QuickSync

설명과 동작 확인용 명령을 참조하였습니다.

이 글에서 참조한 링크

Jinbaek Lee

일본 외노자입니다.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です