Skip to content

cudacodecモジュールを使って動画デコード処理を行う

atinfinity edited this page Aug 8, 2016 · 36 revisions

cudacodecモジュールを使って動画デコード処理を行う

はじめに

OpenCVのcudacodecモジュールは,CUDAを用いた動画のエンコード/デコード機能を提供しています.ここではcudacodecモジュールの動画デコード機能を使うための手順をまとめています.

注意点

fixed to use NVCUVID in 'cudacodec' module. #6036にて対応がマージされたので2016/8/8時点のmasterブランチでは以降の変更は不要です(OpenCV 3.2に取り込まれる見通し)。

OpenCVソースコード修正

最近のNVIDIA CUDA ToolkitではNVCUVENCが同梱されていないようで,cudacodecモジュールのエンコード処理を使うことができなくなっているようです.そのため,以降の手順に沿ってOpenCVソースコードを修正してエンコード処理を無効化します.

opencv-3.0.0\cmake\OpenCVDetectCUDA.cmake

★の行を削除する.

  if(WITH_NVCUVID)
    find_cuda_helper_libs(nvcuvid)
    if(WIN32) ★
      find_cuda_helper_libs(nvcuvenc) ★
    endif() ★
    set(HAVE_NVCUVID 1)
  endif()

opencv-3.0.0\modules\cudacodec\CMakeLists.txt

★の行を削除する.

if(HAVE_NVCUVID)
  list(APPEND extra_libs ${CUDA_CUDA_LIBRARY} ${CUDA_nvcuvid_LIBRARY})

  if(WIN32) ★
    list(APPEND extra_libs ${CUDA_nvcuvenc_LIBRARY}) ★
  endif() ★
endif()

opencv-3.0.0\modules\cudacodec\src\precomp.hpp

★の行を削除する.

#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>

opencv-3.0.0\modules\cudacodec\src\video_writer.cpp

★の行の条件を#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オプション

以下の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.libopencv_cudacodec300.libをリンクします.
(デバッグ版の場合はopencv_cudev300d.libopencv_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 ×

備考

筆者は以下の環境で動作確認しました.


Menu

Computer Vision

GPGPU

AR

ROS

Docker

Jetson

ARM

プログラミング言語

開発環境

勉強会

Clone this wiki locally