背景
Raspberry PiでH264動画の動画フレームを取得する手段としてOpenCVを使う。H264動画のデコードをCPUで実行すると時間がかかりすぎるので、GPUでデコードできるようにgstreamerをあわせてインストールする。
環境
hardware: Raspberry Pi 3
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 9.9 (stretch)
Release: 9.9
Codename: stretch
手順
gstreamerインストール。
gstreamer1.0-omx-rpiでバージョン指定している理由は後述。
sudo apt install cmake libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-tools libgtk2.0-dev gstreamer1.0-omx=1.0.0.1-0+rpi12+jessiepmg gstreamer1.0-plugins-bad gstreamer1.0-plugins-good
gstreamerがh264のハードウェアアクセラレーションに対応しているか確認する。
gst-inspect-1.0 | grep omx
以下のように表示される。
omx: omxmpeg2videodec: OpenMAX MPEG2 Video Decoder
omx: omxmpeg4videodec: OpenMAX MPEG4 Video Decoder
omx: omxh263dec: OpenMAX H.263 Video Decoder
omx: omxh264dec: OpenMAX H.264 Video Decoder
omx: omxtheoradec: OpenMAX Theora Video Decoder
omx: omxvp8dec: OpenMAX VP8 Video Decoder
omx: omxmjpegdec: OpenMAX MJPEG Video Decoder
omx: omxvc1dec: OpenMAX WMV Video Decoder
omx: omxh264enc: OpenMAX H.264 Video Encoder
OpenCVダウンロード。
mkdir OpenCV
cd OpenCV
wget https://github.com/opencv/opencv/archive/4.1.0.zip
unzip 4.1.0.zip
cd opencv-4.1.0
ビルド。
-jオプションの数字を大きくしすぎるとメモリが足りず止まってしまう模様。何度か-jの値を小さくしたり調整した結果ビルド完了まで3~4時間かかってしまった。
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D INSTALL_C_EXAMPLES=OFF -D WITH_1394=OFF -D WITH_GSTREAMER=ON -D WITH_FFMPEG=OFF -D WITH_QT=OFF ..
make -j 4
インストール
sudo make install
pkg-configが使えるようにopencv4.pcファイルを追加する。
sudo mkdir -p /usr/local/lib/pkgconfig
sudo nano /usr/local/lib/pkgconfig/opencv4.pc
Package Information for pkg-config
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/opencv4
Name: OpenCV
Description: Open Source Computer Vision Library
Version: 4.1.0
Libs: -L${exec_prefix}/lib -lopencv_dnn -lopencv_gapi -lopencv_highgui -lopencv_ml -lopencv_objdetect -lopencv_photo -lopencv_stitching -lopencv_video -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_videoio -lopencv_imgcodecs -lopencv_imgproc -lopencv_core
Libs.private: -ldl -lm -lpthread -lrt
Cflags: -I${includedir}
サンプルコードを実行してみる。
#include <opencv2/opencv.hpp>
int main(int argc, char *argv[])
{
cv::VideoCapture gstreamer;
gstreamer.open("videotestsrc ! appsink");
if (!gstreamer.isOpened())
{
printf("=ERR= fail to open\n");
return -1;
}
cv::Mat GstCap;
gstreamer >> GstCap;
cv::imwrite("test.jpg",GstCap);
return 0;
}
コンパイル&実行
g++ `pkg-config --cflags opencv4` gstreamer_test.cpp -std=c++11 -g `pkg-config --libs opencv4` -o gstcvtest
./gstcvtest
test02.jpgとしてカラーバーが表示される。
h264動画をキャプチャしてみる。
使用した動画はここからダウンロード。
https://www2.nhk.or.jp/archives/creative/material/view.cgi?m=D0002040402_00000
#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char *argv[])
{
cv::VideoCapture gstreamer;
//gstreamer.open("filesrc location=/home/pi/nfs/experiment/movie/D0002040402_00000_V_000.mp4 ! qtdemux name=demux demux.video_0 ! h264parse ! omxh264dec ! videoconvert ! appsink");
gstreamer.open("/home/pi/nfs/experiment/movie/D0002040402_00000_V_000.mp4");
if (!gstreamer.isOpened())
{
printf("=ERR= fail to open\n");
return -1;
}
int i=0;
cv::Mat GstCap;
gstreamer.read(GstCap);
cv::imwrite("nfs/preview.jpg",GstCap);
while (gstreamer.read(GstCap))
{
std::cout << "frame=" << i << std::endl;
i++;
}
return 0;
}
コンパイル&実行
g++ `pkg-config --cflags opencv4` h264test.cpp -std=c++11 -g `pkg-config --libs opencv4` -o h264test
time ./h264test
結果。timeコマンドのログ。
1083フレームを37秒なので、29fps程度。
real 0m37.376s
user 0m22.739s
sys 0m4.799s
性能比較
GPUを使わない場合との性能比較を行う。
openの引数に単にファイル名を指定する。
gstreamer.open("/home/pi/nfs/experiment/movie/D0002040402_00000_V_000.mp4");
結果。
real 0m42.042s
user 0m26.877s
sys 0m4.827s
? あまり変わらない。単純にファイル名を指定した場合でもGPUが使用されているということか。
一度GPU用のプラグインを削除してみる。
sudo apt remove gstreamer1.0-omx
結果。激遅
real 7m9.670s
user 7m14.918s
sys 0m0.620s
ここでバージョン指定せずにgstreamer1.0-omxを入れてみる。
1.10.4-1+rpt3が入る。
gstreamerパイプラインをopenに記述して実行してみる。
real 1m44.353s
user 1m38.168s
sys 0m3.689s
このくらい遅い。なぜだろう?