ffmpeg 分辨率 压缩_用GPU加速FFmpeg中的超分辨率功能
1. 簡要回顧
首先簡單復述一下FFmpeg中對深度學習的支持情況,如上圖所示,FFmpeg在libavfilter中支持基于深度學習的filter,目前已經支持sr, derain和dnn_processing等filter,其中,dnn_processing是一個通用的filter,涵蓋了sr和derain的功能,本文將要介紹的超分辨率(Super Resolution)功能也將使用dnn_processing來完成。
為了實現模型推理功能,FFmpeg提供了三種不同的方式(被稱為后端backend),分別是native 后端、tensorflow后端和openvino后端。native后端的所有代碼實現都在FFmpeg代碼樹中,目前以C語言的形式存在,可以跑在各種host端CPU上。tensorflow后端是指FFmpeg調用動態庫libtensorflow.so進行模型加載和推理,可以跑在x86 cpu、NV GPU等各類計算設備上。openvino后端是指FFmpeg調用動態庫libinference_engine_c_api.so進行模型加載和推理,可以跑在x86 cpu、Intel GPU等各類計算設備上。順便提一下,由于FFmpeg的要求,不能調用C++接口,所以這些動態庫都是提供C語言接口的庫文件。
另外,在filter和后端之間,設計了一個用來解耦的接口層DNN interface,這樣,filter可以很方便的從這個后端切換到另外一個后端,方便FFmpeg的開發者和用戶無需修改代碼,只需簡單修改參數即可無縫切換到不同的計算設備上。
接下來將介紹如何使用tensorflow后端在NV GPU上加速Super Resolution,以及如何使用OpenVINO后端在Intel GPU上加速Super Resolution。
2. 資料準備
Super Resolution最本質上就是對視頻圖片的放大,在深度學習技術的加持下效果更好。我們采用ESPCN模型(Efficient Sub-Pixel Convolutional Neural Network model),這是論文地址https://arxiv.org/abs/1609.05158。這個模型的實現非常簡潔,用了4層,依次是64個5x5的卷積層,32個3x3的卷積層,4個3x3的卷積層,卷積層的參數都是same,維持feature map尺寸不變;最后一層是depth2space層,將最后的4個feature map轉換為長寬都乘以2的一張圖片。
所有的模型文件和測試碼流都已經放在了https://github.com/guoyejun/dnn_processing/tree/master/sr1080p, 可以直接下載。其中,onemin960x540.mp4是時長1分鐘960x540分辨率的一段碼流,用于輸入測試;espcn.pb是tensorflow格式的模型文件;我們通過OpenVINO提供的格式轉換工具,將espcn.pb文件轉換成OpenVINO的格式,由于一些限制,OpenVINO格式文件對輸入圖片的大小有具體的數值要求(這個限制可以在OpenVINO后端中解決,但是尚未完成),所以,我們將使用espcn1080p.bin和espcn1080p.xml模型文件,來實現將輸入的960x540分辨率的碼流,轉換成1080p(1920x1080分辨率)的碼流。
要使用TensorFlow后端,只需要下載onemin960x540.mp4和espcn.pb;要使用OpenVINO后端,則需要下載onemin960x540.mp4、espcn1080p.bin和espcn1080p.xml。
3. 用NV GPU加速SR功能
要用NV GPU,軟件庫的調用關系是:FFmpeg -> TensorFlow -> cuDNN -> CUDA。其中的TensorFlow必須是提供C語言接口的庫文件,而通過pip install tensorflow命令安裝的軟件包里面并不包含c接口的庫。為了得到c接口的庫文件,一種方法是我們從TensorFlow源代碼開始編譯出c接口庫文件,但是往往涉及到各種選項,并不是一件容易的事情。另外就是使用TensorFlow的預編譯好的c庫文件,下載其中的Linux(支持 GPU)版本。很不幸的是,目前預編譯的最新2.3 GPU版本存在問題,而預編譯中的上一版本則是1.15,所以,我們只能選擇TensorFlow 1.15 GPU的c庫文件 。
選定TensorFlow 1.15后,根據TensorFlow文檔,還需要在系統中安裝配套的cuDNN7.4和CUDA10.0,在原生系統中配置起來太麻煩,我們就用docker image來完成,使用NV給出的官方image。根據NV的release notes,我們找到nvcr.io/nvidia/tensorflow:18.10-py2 是我們需要的image。所以,后續操作如下所示。
// 下載docker image$ docker pull nvcr.io/nvidia/tensorflow:18.10-py2
// 進入container,用了--rm選項,退出的時候container會被自動刪除
$ nvidia-docker run --rm -it --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 nvcr.io/nvidia/tensorflow:18.10-py2
// 以下操作都在container中進行
// 在這個container中已經支持從python調用tensorflow,但是沒有c庫,所以,還需要下載。
# mkdir tfclib
# cd tfclib/
// 下載gpu版本壓縮包。如果這里下載的是cpu版本的壓縮包,那么后續tensorflow會使用cpu進行推理。
# wget https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-gpu-linux-x86_64-1.15.0.tar.gz
# tar zxvf libtensorflow-gpu-linux-x86_64-1.15.0.tar.gz
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/workspace/tfclib/lib/
// FFmpeg默認不支持TensorFlow后端,必須從源代碼重新編譯
# cd /workspace
# git clone --depth=1 https://git.ffmpeg.org/ffmpeg.git
# cd ffmpeg/
# mkdir build
# cd build/
// 準備依賴庫
# apt-get update
# apt install nasm
# ../configure --enable-libtensorflow --extra-cflags="-I/workspace/tfclib/include" --extra-ldflags="-L/workspace/tfclib/lib"
# make
// 下載測試資料
# wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/onemin960x540.mp4
# wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/espcn.pb
// 運行測試
// 這個時候我們在host端運行nvidia-smi,會觀察一些奇怪現象,不知道最新版本是否已經修復。
// 比如,這么輕量級的模型竟然花了90%以上的顯存,我換成python直接運行也是如此。
// 還有,這么輕量級的模型第一次推理竟然花了十多分鐘乃至數十分鐘。第二次運行的一開始也等待了好久。
// 運行結束后,用ffplay等工具檢查一下輸出結果(即視頻文件espcn.tf.gpu.mp4)是否符合預期
# ./ffmpeg -i onemin960x540.mp4 -vf format=yuv420p,dnn_processing=dnn_backend=tensorflow:model=espcn.pb:input=x:output=y -y espcn.tf.gpu.mp4 -benchmark
在有些系統中,可能會插有多塊NV顯卡,我們可以用下面的方法來指定使用其中的一塊或者若干塊顯卡。首先,要用下面的python腳本生成一串字符串:
import tensorflow as tf// 這里的參數0表示指定使用gpu0,如果是"1,2"就表示使用gpu1和gpu2。
// 需要說明的是,這里的數字,可能和nvidia-smi顯示的序號不一致。
gpu_options = tf.GPUOptions(visible_device_list='0')
config = tf.ConfigProto(gpu_options=gpu_options)
s = config.SerializeToString()
b = ''.join("%02x" % int(ord(b)) for b in s[::-1])
print('0x%s' % b)
假如上述python腳本的輸出是0x30012a0332,那么指定使用gpu0的FFmpeg命令行如下所示,將這個字符串作為dnn_procesing的參數傳遞進去。
# ./ffmpeg -i onemin960x540.mp4 -vf format=yuv420p,dnn_processing=dnn_backend=tensorflow:model=espcn.pb:input=x:output=y:options=sess_config=0x30012a0332 -y espcn.tf.gpu.mp4 -benchmark4. 用Intel GPU加速SR功能
要用Intel GPU,目前的軟件庫的調用關系是:FFmpeg -> OpenVINO -> clDNN -> OpenCL。在host系統中,這些軟件庫都用最新版本,是可以從源代碼編譯出來的,而且,默認情況下,OpenVINO的c庫也會被編譯出來。但是,我們還是使用更加簡潔的docker image方案。在https://hub.docker.com/r/openvino/ 可以看到OpenVINO官方給出的image。由于dev image中沒有安裝git,所以在docker run的時候要加上-u root以獲得apt-get install git的權限。在container中,從FFmpeg源代碼開始的過程,和上一小節非常類似,只需要將TensorFlow相關的設置修改為OpenVINO相關的設置即可。所以,我們在這里換一種方法,將這些過程寫到Docker文件中。
首先,創建一個文件,文件名為DockerFile,內容如下所示,主要是在openvino/ubuntu18_dev:2021.1的基礎上增加FFmpeg軟件包。
From openvino/ubuntu18_dev:2021.1USER 0
RUN apt-get update
RUN apt-get install -y git nasm wget
WORKDIR /workspace
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/intel/openvino/inference_engine/lib/intel64:/opt/intel/openvino/inference_engine/external/tbb/lib:/opt/intel/openvino/deployment_tools/ngraph/lib
RUN git clone --depth=1 https://github.com/FFmpeg/FFmpeg ffmpeg && \
cd ffmpeg && \
./configure \
--extra-cflags=-I/opt/intel/openvino_2021/inference_engine/include/ \
--extra-ldflags=-L/opt/intel/openvino_2021/inference_engine/lib/intel64 \
--enable-libopenvino && \
make -j $(nproc) && \
make install
RUN wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/onemin960x540.mp4 && \
wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/espcn1080p.bin && \
wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/espcn1080p.xml
然后,運行以下命令
// 在DockerFile所在的目錄,創建image$ docker build --network=host $(env | grep -E '_(proxy|REPO|VER)=' | sed 's/^/--build-arg /') -t openvino_ffmpeg .
// 上一步得到的image支持CPU、GPU等多個計算設備,下面的命令參數使得container只支持GPU,
// 為什么需要device參數,這是為了OpenCL驅動在container中使用的。
$ docker run -it --rm --device /dev/dri:/dev/dri openvino_ffmpeg:latest
// 下條命令在container中進行
// 運行結束后,用ffplay等工具檢查一下輸出結果(即視頻文件espcn.ov.gpu.mp4)是否符合預期
root@b31ec026f1dc:/workspace# ffmpeg -i onemin960x540.mp4 -vf format=yuv420p,dnn_processing=dnn_backend=openvino:model=espcn1080p.xml:input=x:output=espcn/prediction:options=device=GPU -y espcn.ov.gpu.mp4 -benchmark
以上內容是本人業余時間興趣之作,限于水平,差錯難免,僅代表個人觀點,和本人任職公司無關。
總結
以上是生活随笔為你收集整理的ffmpeg 分辨率 压缩_用GPU加速FFmpeg中的超分辨率功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java feign同时传对象和其他参数
- 下一篇: c# 连接mysql数据库_C#连接My