일러두기
본 글은 원글을 참조 번역하며, 실제로 막힌 부분에 대한 수정이 이뤄져 있습니다.
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에서 자세하게 확인할 수 있습니다.
하드웨어 종별 | 명칭 | 비고 |
CPU | Intel(R) Core(TM) i5-6200 CPU @ 2.30GHz | Sky Lake |
Memory | 8GB | Onboard |
설치 방법
빌드 도구 설치
#빌드에 공통으로 사용할 패키지를 설치 $ 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/lib
는 LD-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
링크 본문에서 변경점 (=현 블로그의 글과 이 링크의 글이 더 유사합니다)
- LD_LIBRARY_PATH에
/usr/local/lib
를 추가하는 순서가 포함되어 있습니다. - LD_LIBRARY_PATH에
/opt/intel/mediasdk/lib/
를 추가하는 순서가 포함되어 있습니다.
Compile FFmpeg for Ubuntu, Debian, or Mint
https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
링크 본문에서 변경점
- 빌드 할 때 폴더를 더 단순하게 사용하고 있습니다.
- QSV 대응을 위해
--enable-libxmf
를 추가하였습니다. - liboam은 소스에서 빌드하지 않고 패키지를 사용하였습니다.
- gnutls 패키지가
--pkg-config-flags="--static"
를 지원하지 않으므로--pkg-config-flags="--static"
를 삭제합니다.
Hardware/QuickSync – FFmpeg
https://trac.ffmpeg.org/wiki/Hardware/QuickSync
설명과 동작 확인용 명령을 참조하였습니다.