SSブログ

Nvidia Video Codec SDK 7.1のサンプルをいじってみる [プログラミング]

Video Codec SDK 8.0は動いてくれなくて、SDK7.1を使ったら動いたという話を以前にしましたが、やっぱり全部は動いてくれそうにないという話。とそれを弄って何とかHandbrakeにつなげていきたい、という地道な作業。

とりあえずNvTranscodeやNvEncodeのサンプルはビルドできたバイナリがきちんと動くことを確かめました。出力されたバイナリもきちんと確認できたし、問題はあってもそこはインプリしていないだけという状態なのがわかって少しホッとしているところ。

エンコードはきちんとNVENCが動いてくれているのはわかったけれど、引っかかったのはNVDECの方。未だLinuxでは動いてくれていない。WindowsではDirectXでのサンプルのビルドが通りきちんと動いたのだが、Linuxと同じくOpenGLの方は動いてくれていない。というか、OpenGL用ではLinuxでは通ったビルドさえ、VisualStudioではエラーを吐いてリンクの時に転んで実行ファイルができない。Windows用のfreeglutとか入れないといけないんだろうか。そもそもWindowsには昔からOpenGLは使えたはずなんだけどな。

http://egolog.hateblo.jp/entry/2016/04/09/212608

で入れ込んだけど、static linkは対応していないとか言われたっぽい。ん〜他のfreeglutとか入れてもconflictなんとかのfreeglut_staticd.lib関係のリンクエラーが取れない。というか、Visual Studioなんだからいろいろ設定して動くようにしておいてほしいんだが…。

とにかくDirectXの方のソースは動いているので、NVDECに渡すところは使えるだろう。でも、ちょっと考えてみたんだが、NVDECってインターレースの処理とかするからGPUでデコードしてCPU側にまた戻して、という処理をしなくちゃいけなくなってしまい面倒な気がしてきた。とりあえずNVENCが使えるところを頑張ってからで後で考えればいいかと思ったのでした。それにTranscodeでh.264に関してはNVDECを使っていると思われるので、そこから掠め取ってくればMPEG2とかにも応用できそうな気はする。ただ渡すパラメーターだけの問題な気はするね、きちんとソース読んでないけど。

そんなわけで、とりあえず今できていないH.265のデータをMP4のコンテナに載せる処理をしてあげないといけない。そこいらの処理はHandbrakeの処理から取ってくる方が後々整合性が取りやすくなりそうだからパクってくる。


NVDECとCUVIDがなんか違うものかなぁと思っていたら、SDKのページにおんなじ物だよと書いてあった。SDKのページはダウンロードに行くだけで全然読んでないなぁ。

https://developer.nvidia.com/nvidia-video-codec-sdk

cuvidという名前はAPIに残ってはいるものの、今はNVDECで良いらしい。ちなみにNVENCの方はcuvid何とかで始まる関数ではなくて、NvEnc何とかという関数になって別箇になってはいる。互換性の問題だとは思うけど、統一性はないわな。別機能と考えられなくはない。

基本NVIDIAのハードウェアCODECはYUVを入出力して加工すると思うので、エンコード前のデコードもGPUでやってしまった方が効率がいいと思われる。GPUでの処理のボトルネックはグラフィックメモリへの転送にあるとは思うので、一気にデータを送ってモニョモニョした方がいいんでしょう。今見ている限りでは、データを意図的にGPUに送るとか単体の関数でやっていないみたいなんだけど、内部的にはGPUのメモリに送ったり戻したりはしているとは思うので、そこを細かくしたい場合はCUDAを使うことになるのかもしれない。

Handbrakeに入れようとすると、MPEG2とかのデータを扱うことになると思うけれども、そこいらのデコードもNVDECでもちろん出来て、そのままNVENCにYUVデータを渡せそう。HandbrakeはQSVのデコードの機能はデフォルトでオンになっていないみたいなので、その分CPUへの負荷は更に軽くなると思われる。なかなかいい感じ。というか、大体の処理がGPU内で終わらせられそうだ。ただし、MP4のコンテナに載せる処理とかはやらないと、動画がDEMUXされたようなネイキッドな状態になってしまうので、Linux以外では普通画像が再生できない。

Handbrakeはc言語で、NVENC、NVDECのサンプルはC++で書かれている。組み入れる時に面倒そうだ。NVDECもNVENCもAPIはC言語の関数になっていると思うんだけど、サンプルがC++で書かれているのは移植に面倒なんだよなぁ。extern"C"すればいいんだろうけど、API自体はC言語で書かれているので、C言語で書き直したほうが早いかもしれない。どっちが楽だろうなぁ。

C言語をC++に入れるのは問題ないとは思うんだけど、逆は気をつけないといけなさそうなのでヤダ。コンパイラも統一できそうもないし結局NVCCでやってた時とそんなに変わらないMakefileの扱いになりそうで今からウンザリ。動けば良いとは思うんだけど、元々あるソースを親子関係にあるとはいえ別の言語で書き直すとかしんどすぎるんですが。ソースそのままで無理やりがっちゃんこした方が、手を加えるのが少なくていいのかもしれない。

HandbrakeはGPUに渡す前までの前処理をすることになるわけだけども、その後のMUXの処理が上手くつながるかどうかが気になるところ。とりあえずTranscodeのソースにMPEG2とかのソースを読み込めるようにして、H.265でエンコーディングしたデータをMP4の形式にしたい。今のTranscodeだとH264しか読み込めないから、そこいらの部分をクリアにして、出力が普通のアプリでは読み込めない状態をHandbrakeのMUX部分をパクって直していく。そこからHandbrakeに組み入れられればと思う。

タグ:NVENC
コメント(0) 
共通テーマ:パソコン・インターネット

コメント 0