-
Notifications
You must be signed in to change notification settings - Fork 13
cudacodecモジュールを使って動画デコード処理を行う
OpenCVのcudacodecモジュールは,CUDAを用いた動画のエンコード/デコード機能を提供しています.ここではcudacodec
モジュールの動画デコード機能を使うための手順をまとめています.
fixed to use NVCUVID in 'cudacodec' module. #6036にて対応がマージされたので2016/8/8時点のmasterブランチでは以降の変更は不要です(OpenCV 3.2に取り込まれる見通し)。
最近のNVIDIA CUDA ToolkitではNVCUVENCが同梱されていないようで,cudacodec
モジュールのエンコード処理を使うことができなくなっているようです.そのため,以降の手順に沿ってOpenCVソースコードを修正してエンコード処理を無効化します.
★の行を削除する.
if(WITH_NVCUVID)
find_cuda_helper_libs(nvcuvid)
if(WIN32) ★
find_cuda_helper_libs(nvcuvenc) ★
endif() ★
set(HAVE_NVCUVID 1)
endif()
★の行を削除する.
if(HAVE_NVCUVID)
list(APPEND extra_libs ${CUDA_CUDA_LIBRARY} ${CUDA_nvcuvid_LIBRARY})
if(WIN32) ★
list(APPEND extra_libs ${CUDA_nvcuvenc_LIBRARY}) ★
endif() ★
endif()
★の行を削除する.
#include "opencv2/cudacodec.hpp"
#include "opencv2/core/private.cuda.hpp"
#ifdef HAVE_NVCUVID
#include <nvcuvid.h>
#ifdef WIN32
#define NOMINMAX
#include <windows.h>
#include <NVEncoderAPI.h> ★
★の行の条件を#if defined(HAVE_NVCUVID) || !defined(WIN32)
に変更する.
#include "precomp.hpp"
using namespace cv;
using namespace cv::cuda;
using namespace cv::cudacodec;
#if !defined(HAVE_NVCUVID) || !defined(WIN32) ★
以下のCMakeオプションをONにしてOpenCVライブラリを生成します.
BUILD_opencv_cudacodec
BUILD_opencv_cudev
WITH_CUDA
WITH_NVCUVID
コマンドラインでCMakeを実行する場合は以下のようなオプションを付与することで同様のことが行えます.
-D BUILD_opencv_cudacodec=ON ^
-D BUILD_opencv_cudev=ON ^
-D WITH_CUDA=ON ^
-D WITH_NVCUVID=ON ^
ライブラリはopencv_cudev300.lib
,opencv_cudacodec300.lib
をリンクします.
(デバッグ版の場合はopencv_cudev300d.lib
,opencv_cudacodec300d.lib
)
また,ヘッダファイルはopencv2/cudacodec.hpp
をインクルードします.
cudacodec
モジュールを使って動画デコード処理を行うサンプルコードです.
#include <opencv2/core.hpp>
#include <opencv2/core/opengl.hpp>
#include <opencv2/cudacodec.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
int main(int argc, const char* argv[])
{
if (argc != 2) return -1;
const std::string fname(argv[1]);
cv::namedWindow("GPU", cv::WINDOW_OPENGL);
cv::cuda::setGlDevice();
cv::cuda::GpuMat d_frame;
cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader(fname);
std::vector<double> gpu_times;
double f = 1000.0f / cv::getTickFrequency();
int64 start = 0;
int64 end = 0;
for (;;)
{
start = cv::getTickCount();
if (!d_reader->nextFrame(d_frame))
break;
end = cv::getTickCount();
gpu_times.push_back((end - start) * f);
cv::imshow("GPU", d_frame);
if (cv::waitKey(1) > 0)
break;
}
if (!gpu_times.empty())
{
std::cout << std::endl << "Results:" << std::endl;
std::sort(gpu_times.begin(), gpu_times.end());
double gpu_avg = std::accumulate(gpu_times.begin(), gpu_times.end(), 0.0) / gpu_times.size();
std::cout << " GPU : Avg : " << gpu_avg << "[ms], FPS : " << 1000.0 / gpu_avg << std::endl;
}
return 0;
}
-
cudacodec
モジュールのエンコード処理がサポートする動画フォーマット,コーデックには制限があるようです. - そのため,サポート外の動画フォーマット,コーデックとなる動画ファイルは扱うことができません.
筆者の環境(Windows 8.1 Pro with Media Center)にてopencv_extra にあるテストデータを用いたデコード成否結果を参考までに下記の表にまとめました.
ファイル名 | コーデック | FourCC | デコード成否 |
---|---|---|---|
big_buck_bunny.avi | XviD | XVID | ○ |
big_buck_bunny.mov | MPEG4 Visual | mp4v | ○ |
big_buck_bunny.mp4 | MPEG4 Visual | mp4v | ○ |
big_buck_bunny.mpg | MPEG1 | MPEG1 | × |
big_buck_bunny.wmv | Microsoft MPEG-4 Video Codec V3 | MP43 | × |
筆者は以下の環境で動作確認しました.