ffmpegの h264_qsvはCPUを使ってくれない

早速ffmpegのh264_qsvでDLNAのトランスコードを試しています。使い方を判っていないのか、何か変な動作をします。

今のところ、変換が遅い、映像と音声の同期がとれない、という状況です。

今回使ったffmpegはZeranoe FFmpeg様の32bitスタティックビルドの ffmpeg-20150610-git-913685f-win32-static.7z です。
動かしているパソコンのマザーボードはASUSのP8H67-V、CPUがSandy Bridge世代 Core i5 2500Tです。ベースクロック2.3GHz、GPU650MHzです。GPUはIntel® HD Graphics 2000 となります。

BMS2用のLuaスクリプトをいじってそれっぽく動くようにしてみました。ffmpegのコマンドとしては次のようなものになります。

ffmpeg -itsoffset 1 -i "TEST.mkv"  -c:v h264_qsv -r 30000/1001   -q 22  -threads:a 0 -async 1000  -c:a:0 copy  -c:a:1 copy  -movflags faststart   -filter_complex "[s:0]scale=w=iw/1:h=ih/1[sub];[v:0][sub]overlay=(W-w)/2:(H-h):eval=init,scale=1920:1080,setsar=40/33,yadif=0:-1,drawtext=enable='lte(n\,390)':box=1:boxcolor=00000040:fontfile='C\:/Windows/Fonts/msgothic.ttc':fontcolor=00FF00:fontsize=72:x=if(lte(n\, 360)\, 20\, 20+(360-n)*(20+tw)/30):y=line_h:text='frame=%{n}\:Matroska\:AVC\:QSV Transcode',drawtext=enable='lte(n\,360)':box=1:boxcolor=00000040:fontfile='C\:/Windows/Fonts/msgothic.ttc':fontcolor=00FF00:fontsize=72:x=if(lte(n\, 330)\, 20\, 20+(330-n)*(20+tw)/30):y=line_h*2:text='1\:ja\:2Ch\:AAC\: 2\:en\:2Ch\:AAC\:',drawtext=enable='lte(n\,300)':box=1:boxcolor=00000040:fontfile='C\:/Windows/Fonts/msgothic.ttc':fontcolor=00FF00:fontsize=72:x=if(lte(n\, 270)\, 20\, 20+(270-n)*(20+tw)/30):y=h-line_h*3:text='w=1920, h=1080, dar =1.778, par =1',drawtext=enable='lte(n\,330)':box=1:boxcolor=00000040:fontfile='C\:/Windows/Fonts/msgothic.ttc':fontcolor=00FF00:fontsize=72:x=if(lte(n\, 300)\, 20\, 20+(300-n)*(20+tw)/30):y=h-line_h*2:text='x=1920, y=1080, dar2=1.778, par2=1',setpts=PTS-STARTPTS[video]"  -f mpegts -mpegts_m2ts_mode -1 -g 15 -packetsize 188  -threads 6 -map [video] -map 0:a:0 -streamid 0:33 -streamid 1:34 -map 0:a:1 -streamid 2:35 -y "TestOut.m2ts"

無駄に長いですがテキスト書き込みと字幕オーバーレイのフィルタが長いだけです。
今回のエンコードに絡む所だけにすると

ffmpeg -itsoffset 1 -i "TEST.mkv"  -c:v h264_qsv -r 30000/1001   -q 22  -async 1000  -c:a:0 copy  -movflags faststart  -f mpegts -mpegts_m2ts_mode -1 -g 15 -packetsize 188  -threads 6  -y "TestOut.m2ts"

これだけですね。
そもそもh264_qsvを使う時のビットレート指定とか品質指定などオプションがどうなっているか判りません。ffmpeg -h full に書いてあるのだけでしょうか? GOP長の指定はこれで反映されるのでしょうか? 参照フレーム数はどうなるんだろう? まずはエンコードできるかどうかが肝心ですね。

コマンドプロンプトから実行させると何やら警告メッセージが表示されますがエンコードはできるようです。次のようなメッセージが表示されました。

[mpegts @ 04bc0d20] Non-monotonous DTS in output stream 0:0; previous: 78, curre
nt: 0; changing to 79. This may result in incorrect timestamps in the output fil
e.
frame=   83 fps= 56 q=0.0 size=      19kB time=00:00:01.96 bitrate=  80.6kbits/s
[mpegts @ 04bc0d20] Non-monotonous DTS in output stream 0:0; previous: 79, curre
nt: 0; changing to 80. This may result in incorrect timestamps in the output fil
e.
[mpegts @ 04bc0d20] Non-monotonous DTS in output stream 0:0; previous: 80, curre
nt: 0; changing to 81. This may result in incorrect timestamps in the output fil
e.

Non-monotonous DTS in output stream xxx というメッセージが出てきます。タイムスタンプが正しく記録されないとの警告のようですがどうやって修正するのか判りません。
dtsとかptsのタイムコードはm2tsに使うので出力フォーマットを別のものにすると警告は無くなります。けど根本的な解決ではないですしDLNA配信できないフォーマットになってしまいます。
検索するとh264_qsvだけでは無くいろいろなところで生じているエラーのようです。基本的にバグのようですので何もできそうにありません。

さて、警告は無視して他の面をみてみます。
上のメッセージに変換している速度があります。fps = 56という所です。これは遅いです。HandbrakeやQSVEncCなど他のQSVエンコードなら120fpsは出ている所です。
本当にハードウエアエンコードしているのか不安になってきました。そういえばハードウエアを使っているか確かめる方法を知りません。今までは圧倒的なエンコード速度でハードウエアを使っていると実感していました。

まずはエンコード中のCPU負荷を見てみます。

h264_qsvでエンコード中
CPUの利用率が低いです。GPUクロックは650MHzですがGPUブーストを1800MHzまでかけるようにしています。GPUを使えばもっとクロックが上がるはずなんですよね。
出来上がったファイルを見ると確かにh264でエンコードされています。ソフトウエアでこのCPU負荷なら56fpsの速度は出ません。つまりGPUは使われているようです。

ちなみにHandbrakeでqsvエンコードを行うと

Handbrake

となります。GPUブーストがかかるのでハードウエアを使っているのが判ります。
ffmpegではシングルスレッド動作に強制されているようにも見えます。

BMS2を使ってテレビで映るかもテストしました。
なんとかテレビに映りました。しかし、音声の同期がずれています。最初の10秒ほど音声が出ません。その後映像と数秒ずれた音声が出ます。やはりタイムスタンプがおかしそうです。しかし、上のコマンドで作ったm2tsファイルをmpc-beなどパソコンのプレーヤで再生すると意外と大丈夫だったりします。
エンコード速度もリアルタイムトランスコードには余裕が無く時々変換が間に合わないようです。字幕をオーバーレイするとガクガク。

以上、簡単にffmpegのh264_qsvのエンコードを試して見ました。まだ使える感じではないです。
現在はQSVを使ったトランスコードにQSVEncCを使っています。変換には標準入出力のパイプ処理を4段も使っています。そのため応答が遅いのが欠点です。早送りや30秒スキップを多用するとBMS2がフリーズしてしまう事が頻発。そのためほとんどQSVは使っていません。今回のh264_qsvが使えればパイプ処理も不要になりQSVのトランスコードが使えるようになるので今後に期待しています。

余談ですがQSVを使うなら必ず品質を指定するようにしましょう。QSVは汚いと言われますがまずはビットレート指定していないか確認しましょう。可変ビットレートでもダメです。ビットレート指定はmpeg2時代の遺物です。x264に比べれば確かに汚いですが処理時間と電力消費を考えればとてもきれいです。

コメント

最近のコメント

Threaded Recent Comments will be here.