H.264エンコーダの画質評価を行う

 先日JPEGで行ったのと同様の画質評価をH.264の各種エンコーダでも行いました。
wave.hatenablog.com

 今回はH.264エンコーダとしてlibx264, intel QSV, AMD AMF(VCE)を使用して、その劣化の程度がどの位なのか定量的に評価を行ってみました。
 

評価対象

  • ソフトウェアエンコーダ
    • libx264
  • ハードウェアエンコーダ

 なお、いずれのエンコーダもffmpegから利用して評価します。
 

評価方法

 今回も元映像に対してどれだけ劣化したかを評価するために、PSNR(Peak Signal to Noise Ratio)を使います。
 JPEGエンコーダを評価した時との違いは、静止画ではなく動画であることですが、動画は複数枚の静止画から構成されているに過ぎないので、各フレームに展開した状態で評価します。
 

評価用マスタ映像(画像群)

 今回は30fpsで10秒、すなわち毎秒30枚×10=300枚の画像で構成されるイメージシーケンスを生成して評価用マスタ映像とします。ffmpegで生成可能ですが、解像度は1920x1080(Full HD)とし、ffmpegが出力する時点で非可逆圧縮されたくないので、マスタ画像はPNGで生成します。
評価用マスタ画像

 お手元の環境で追試する場合は、以下のコマンドで今回使用した評価用マスタ画像(MASTER_FRAME_0001~0300.png)と同じ画像を生成可能です。

ffmpeg -f lavfi -i testsrc=rate=30:size=1920x1080:duration=10 MASTER_FRAME_%04d.png

 

検証

 具体的にエンコードとフレーム画像への展開は以下のコマンドを叩きました。

# libx264 (slow preset)
ffmpeg -r 30 -i MASTER_FRAME_%04d.png -c:v libx264 -pix_fmt yuv420p -g 30 -preset slow -y testsrc_x264_slow.mp4
# libx264 (fast preset)
ffmpeg -r 30 -i MASTER_FRAME_%04d.png -c:v libx264 -pix_fmt yuv420p -g 30 -preset fast -y testsrc_x264_fast.mp4

## i5-5300u搭載機で実行
# intel QSV (slow preset)
ffmpeg -r 30 -i MASTER_FRAME_%04d.png -c:v h264_qsv -pix_fmt yuv420p -g 30 -preset slow -y testsrc_i5-5300u_qsv_slow.mp4
# intel QSV (fast preset)
ffmpeg -r 30 -i MASTER_FRAME_%04d.png -c:v h264_qsv -pix_fmt yuv420p -g 30 -preset fast -y testsrc_i5-5300u_qsv_fast.mp4

## i5-4300u搭載機で実行
# intel QSV (slow preset)
ffmpeg -r 30 -i MASTER_FRAME_%04d.png -c:v h264_qsv -pix_fmt yuv420p -g 30 -preset slow -y testsrc_i5-4300u_qsv_slow.mp4
# intel QSV (fast preset)
ffmpeg -r 30 -i MASTER_FRAME_%04d.png -c:v h264_qsv -pix_fmt yuv420p -g 30 -preset fast -y testsrc_i5-4300u_qsv_fast.mp4

# h264_qsvをエンコーダに指定した場合、以下のメッセージが出力され、pix_fmtがyuv420pではなくnv12が使われます
# yuv420とnv12ではデータの持たせ方というか各成分のメモリ上の並び順が違いますが、YUV各成分が持っている情報量は同じなので検証には差し支えありません
#  Incompatible pixel format 'yuv420p' for codec 'h264_qsv', auto-selecting format 'nv12'

## RX470搭載機で実行
# AMD AMF
ffmpeg -r 30 -i MASTER_FRAME_%04d.png -c:v h264_amf -pix_fmt yuv420p -g 30 -preset slow -y testsrc_rx470_amf_slow.mp4
ffmpeg -r 30 -i MASTER_FRAME_%04d.png -c:v h264_amf -pix_fmt yuv420p -g 30 -preset fast -y testsrc_rx470_amf_fast.mp4

# h264_amfをエンコーダに指定した場合、以下のメッセージが出力され、preset指定は無効となります
# slowでもfastでも同じエンコード結果となりますので、AMD AMFの検証データパターンは1つのみになります
#  h264_amf shows message: Codec AVOption preset (Configuration preset) specified for output file #0 (testsrc_rx470_amf_slow.mp4) has not been used for any stream. The most likely reason is either wrong type (e.g. a video option with no video streams) or that it is a private option of some encoder which was not actually used for any stream.

# フレーム画像への展開(各テストパターンごとに実行)
ffmpeg -i testsrc_%ID%.mp4 testsrc_%ID%_FRAME_%04d.png

 

PSNR測定結果

 縦軸をPSNR、横軸をフレーム番号(1~300)としてグラフにプロットすると以下の通り。
H.264 PSNR comparison

 グラフ中にも書き入れましたが、QSVの全4パターン(i5 5300u/4300u, preset slow/fast)に共通して最初の60フレームのPSNRが低いのが目立ちます*2
 
 このグラフでは差異が見にくいので、PSNR下限値を37.4にしてグラフの上の方を拡大してみます。
H.264 PSNR comparison (zoomed)
 

まとめ

 これらよりの結果から、概ね以下のような傾向が見受けられると言えます。

  • libx264もQSVもpreset slow/fastの違いによるPSNRの変化は少ない
    • (個人的にpreset指定は画質と所要時間のトレードオフだと誤解していましたが、出力ファイルサイズと所要時間のトレードオフで画質は無関係なようです)
  • QSVの先頭60フレームは低PSNRだが、240フレーム前後ではどのエンコーダよりも優れたPSNR
  • (QSVの先頭60フレーム部分を除き、)エンコーダに依らずPSNR変化の波形は類似
  • テストパターン内ではAMFが最も安定して高PSNRを維持

 テスト条件下ではQSVの先頭60フレームを除けばどのエンコーダーでもPSNRは概ね37.5~38程度と大差は無いことが定量的に判断できますので、画質観点からは任意のエンコーダを選択すればよいのではないかと思います。ただし、今回は所要時間、出力ファイルサイズ、ビットレート等、エンコーダの他の重要な指標について何も比較・評価していません。常用するエンコーダを選定する上では、これらの指標についても検討する必要がありますので、別途まとめる予定です。
 なお、このPSNR値はJPEGの場合、ImageMagickのquality1~100で表すところの89と90の間、Photoshopの品質0~12で表すところの6と7の間に相当する画質です。そう考えると控えめな画質だと思いますが、任意の時間見ることができる静止画とは異なり、一般に映像の各フレームは約0.03秒(1/30秒; 30fpsの場合)や、長くても約0.04秒(1/24秒; 24fpsの場合)しか表示されません。故に細かな劣化は気付きにくく、ほとんど知覚されないことから、この程度のPSNRでも実用上の問題は無いのでしょう。
 



以上。

*1:各エンコーダの細かいパラメータ設定を試していると、組み合わせが膨大になるため。

*2:今回GOPは30に指定していますので、60フレームではなくもしかして最初の2GOPが低PSNRになるのかと思い、GOPを変えて実験してみましたが、GOPに依らず常に最初の60フレームのPSNRが同様に低い結果となりました。