LoginSignup
30
17

More than 5 years have passed since last update.

cudacodecモジュールを使ってみよう

Last updated at Posted at 2016-12-19

この記事はOpenCV Advent Calendar 2016の20日目の記事です.

はじめに

この記事ではWeb上で語られることが少ないcudacodecモジュールについて紹介します.

cudacodecモジュールとは

OpenCVのcudacodecモジュールはGPUを用いて動画のエンコード/デコードを行うための機能を提供しています.また,内部的にはNVIDIA VIDEO CODEC SDKを使って実装されています.

このモジュールのAPIについては公式ドキュメントを参照下さい.

NVIDIA VIDEO CODEC SDKとは

NVIDIA VIDEO CODEC SDKでは動画のエンコード/デコード処理をGPUで行うためのAPIが提供されています.以下にNVIDIA VIDEO CODEC SDK公式サイトにある図を引用します.

VCSDK_001_b.png

この図からもわかるようにNVDEC,NVENCにてGPUを用いて動画のデコード処理,エンコード処理を行います.また,GPUのアーキテクチャによってサポートする機能,コーデック等が異なる点に注意が必要です.詳細は下記ページを参照ください.

cudacodecモジュールを有効にする方法

ただし,OpenCV 3.1時点のcudacodecモジュールにはバグがあるため,そのままではこれらの機能を有効にすることができません.

そのため,cudacodecモジュールを有効にするためには以下の変更(筆者のプルリク)を適用して下さい.この変更はmasterブランチにマージされているためOpenCV 3.2以降では特にこの変更なしで有効にできるはずです.

また,cudacodecモジュールとは直接関係ありませんが,今回の開発環境(VS2015CUDA8.0)でOpenCV 3.1を動作させるために以下の変更も適用しています.

さらにこちらを読むとわかるように今回用いたGeForce GTX 1060ではハードウェアでH.265を処理できるため,cv::cudacodec::detail::VideoDecoder::create関数に

cudaVideoCodec_HEVC  == _codec ||

という条件式を追加し,H.265のファイルも処理できるようにしています(この条件式を追加しないとASSERTが起きてしまう).

CMakeオプション

cudacodecモジュールを有効にするには以下のCMakeオプションをONにしてOpenCVライブラリをビルドする必要があります.

  • BUILD_opencv_cudacodec
  • BUILD_opencv_cudev
  • WITH_CUDA
  • WITH_NVCUVID

実装手順

ここまでの手順でライブラリ生成ができるようになったので実装手順に入ります.
cv::cudacodec::VideoReaderクラスを使った実装手順は以下の通りです.

  1. cv::cudacodec::VideoReaderクラスのインスタンスを生成する
  2. cv::cudacodec::VideoReaderクラスのnextFrameメソッドで1フレームデコードする

以下にこの手順に従ったサンプルコードを示します.

// cv::cudacodec::VideoReaderクラスのインスタンスを生成する
cv::Ptr<cv::cudacodec::VideoReader> d_reader = cv::cudacodec::createVideoReader("hoge.mpg");

cv::cuda::GpuMat d_frame;

// 1フレームデコードする
d_reader->nextFrame(d_frame)

パフォーマンス計測

以下のURLにあるテストデータを用いて1フレーム当たりのデコード時間を計測しました.

また,処理時間を計測するために用いたテストプログラムはこちらを参照ください.各ファイルに対するCPU処理(cv::VideoCapture )、GPU処理(cudacodec::createVideoReader)のデコード時間は以下の通りです.

ファイル名 コーデック 画像サイズ cv::VideoCapture cv::cudacodec::createVideoReader
1920x1080.avi MPEG-4 1920x1080 3.99ms 0.82ms
jellyfish-10-mbps-hd-h264.mkv H.264 1920x1080 3.90ms 0.56ms
jellyfish-10-mbps-hd-hevc.mkv H.265 1920x1080 4.03ms 0.56ms
jellyfish-50-mbps-hd-h264.mkv H.264 1920x1080 4.10ms 0.56ms
jellyfish-50-mbps-hd-hevc.mkv H.265 1920x1080 4.86ms 0.56ms
jellyfish-100-mbps-hd-h264.mkv H.264 1920x1080 4.48ms 0.57ms
jellyfish-100-mbps-hd-hevc.mkv H.265 1920x1080 6.35ms 0.56ms
TRM10098_01.MOV H.264 1920x1080 6.97ms 1.51ms
TRM10115_01.MOV H.264 1920x1080 6.50ms 1.49ms

上記の結果からもcudacodec::createVideoReaderを使うことで高速にデコード処理を行うことができていることがわかります(お使いのGPUによって速度は変わると思います).

ただし,http://www.jell.yfish.us/にあるMain10プロファイルのものは2016/12/18時点で正しく処理できませんでした.これはおそらくhttps://developer.nvidia.com/nvidia-video-codec-sdk#NVDECFeaturesにある

* HEVC/VP9 10/12 bit decoding SW support coming in Video Codec SDK 8.0

という制約のためだと考えられます.また,コーデックやプロファイルによってはデコード結果が正しくない場合もあるため,使用する前に確認しておくとよいでしょう.

TODO

また,現時点でのcudacodecモジュールに関する積み残しは以下の通りです.
ご興味ある方は対応してPRを投げてみてください!

  • cudacodecモジュールの非Windows対応
    • CMakeのFindCUDACUDA_nvcuvid_LIBRARYを見つけられるのは現状Windowsのみなので,Linux側の処理を書いてあげる必要あり
  • cv::cudacodec::detail::VideoDecoder::create関数のHEVC対応
    • GPUのアーキテクチャによって対応コーデックが異なるのでその辺をちゃんとハンドリングしながらチェックする必要があるはず
  • cudacodecモジュールのエンコード処理対応
    • NVEncode APIを使った実装が必要

おわりに

この記事ではWeb上で語られることが少ないcudacodecモジュールについて紹介しました.正しくデコードできるかの動作確認は必要になるものの,動画のデコード処理時間を短縮できる魅力的な機能なので利用を検討してみてもよいかもしれません.

備考

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

  • CPU:Intel Core i7-6700HQ
  • メモリ:64GB
  • GPU:NVIDIA GeForce GTX 1060 / 6GB
  • Windows 10 Pro(64bit)
  • OpenCV 3.1.0
  • CUDA 8.0
  • Visual Studio 2015 Professional
30
17
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
17