« Chikuzen氏のavs2pipemodとRawSourceの記事へのリンクwith変更履歴 | トップページ | FlashPlayer11.2.202.228以降で発生する問題と対処方法 »

2012年3月21日 (水)

RGB24をx264(10bit)のi444で可逆圧縮し、どれだけ同じ色を保持できるか調べる。

※この記事はまだ暫定公開の段階であり、現在継続調査中です。
  ディザ処理やデコードなど、挙動がいまいちよくわからない部分がでてきたので、
  今の時点の記事はあまり参考にしないほうがよいです。

※RGB24は、x264(8bit)で--output-csp rgbでエンコードすればRGBのまま圧縮できます。
  この記事は、
     「RGB24を10bitYUV化した場合にどこまで正確に色を保持できるか」
  という実験目的で書いたものです。


■使用ツール
  Avisynth 2.6 Alpha3
  dither v1.14.1
  masktools v2.0 a48
  flash3kyuu_deband v1.5.0
  avs2pipemod v0.4.1
  x264 r2184 32bit 10bit-depth (x264.nl)

■画像ファイル
  こちらのサイトにある4096x4096のall16777216rgb.pngを、2048x2048に4分割したもの。
  元画像には、RGB24で表せる16777216色全てが含まれている。

■使用したavsファイル(これをベースに、色々なパターンにあわせて必要箇所だけ利用)

LoadPlugin("D:\MovieTool\Avisynth\masktools-v2.0a48\mt_masktools-26.dll")
LoadPlugin("D:\MovieTool\Avisynth\dither-1.14.1\dither.dll")
Import("D:\MovieTool\Avisynth\dither-1.14.1\dither.avsi")
LoadPlugin("D:\MovieTool\Avisynth\flash3kyuu_deband_1.5.0_x86\flash3kyuu_deband.dll")

ImageSource("allRGB左上.png",end=1,fps=1)

# RGB24をstack16形式の16bitYUVに変換する。
#Dither_convert_rgb_to_yuv(matrix="601",tv_range=true,lsb=true,mode=-1,output="YV24") 

# Ditherのドキュメントに書いてあった「10bit深度相当にする方法」。ただし出力ビット深度は16。
/*
a = Dither_get_lsb ()
b = Dither_get_msb ()
c1 = a.mt_lut ("x 6 >>",        y=3, u=3, v=3)
c2 = a.mt_lut ("x 2 << 255 &u", y=3, u=3, v=3)
DitherPost (c1, c2, mode=1)	# Add the mode you want and other parameters here
mt_lut ("x 6 <<", y=3, u=3, v=3)
StackVertical (b, last)
*/

# stack16形式の16bitYUVを、f3kdb()で10bitのinterleaved formatで出力する
#
# ・sample_mode=0は廃止予定らしいのでsample_mode=1にしてgrainY,grainCを0にしてみた。
#  sample_mode=0だとdither_algoは0(8bit processing)だけしか使えず、しかもこれも廃止予定らしいし、
#  さらにdither_algo=0だとoutput_mode=0、つまり8bit出力しかできない。
# ・dither_algo=1(ディザ無しでLSBを丸めるだけ)とした。
# ・input_mode=1はstacked format
# ・output_mode=2はinterleaved format
# ・output_depthで10bit出力を選ぶ
#
/*
f3kdb(range=0,Y=0,Cb=0,Cr=0,grainY=0,grainC=0,sample_mode=1,dither_algo=1, \
         keep_tv_range=true,input_mode=1,input_depth=16, \
         output_mode=2,output_depth=10)
*/

# stack16形式の16bitYUVを実質YUV4xxp16となるinterleaved formatにする
#Dither_convey_yuv4xxp16_on_yvxx ()

■avsの例

 ●Ditherで16bit(Rec601)にして16bitのinterleaved formatで出力するavs

LoadPlugin("D:\MovieTool\Avisynth\masktools-v2.0a48\mt_masktools-26.dll")
LoadPlugin("D:\MovieTool\Avisynth\dither-1.14.1\dither.dll")
Import("D:\MovieTool\Avisynth\dither-1.14.1\dither.avsi")
ImageSource("allRGB右下.png",end=1,fps=1)
Dither_convert_rgb_to_yuv(matrix="601",tv_range=true,lsb=true,mode=-1,output="YV24") 
Dither_convey_yuv4xxp16_on_yvxx()

 ●Ditherで16bit(PC.709)にしてからf3kdbで10bitのinterleaved formatで出力するavs

LoadPlugin("D:\MovieTool\Avisynth\masktools-v2.0a48\mt_masktools-26.dll")
LoadPlugin("D:\MovieTool\Avisynth\dither-1.14.1\dither.dll")
Import("D:\MovieTool\Avisynth\dither-1.14.1\dither.avsi")
LoadPlugin("D:\MovieTool\Avisynth\flash3kyuu_deband_1.5.0_x86\flash3kyuu_deband.dll")
ImageSource("allRGB右下.png",end=1,fps=1)
Dither_convert_rgb_to_yuv(matrix="709",tv_range=false,lsb=true,mode=-1,output="YV24") 
f3kdb(range=0,Y=0,Cb=0,Cr=0,grainY=0,grainC=0,sample_mode=1,dither_algo=1, \
         keep_tv_range=true,input_mode=1,input_depth=16, \
         output_mode=2,output_depth=10)

 ●RGB24をそのまま出力するavs

ImageSource("allRGB右下.png",end=1,fps=1)

■avs2pipemodを用いたエンコードのコマンド例

 ●Ditherで16bit(PC.709)→x264(10bit)の例 (フルレンジなので--input-range pcをつけている)
   avs2pipemod_0_4_1.exe -rawvideo allRGB左上-Dither16-PC709.avs | x264_r2184_10bit.exe  - --demuxer raw --input-csp i444 --input-depth 16 --input-res 2048x2048 --input-range pc --output-csp i444 --frames 2 --fps 1/1 --qp 0 --colormatrix bt709 -o allRGB左上-Dither16-PC709.mp4

 ●Ditherで16bit(Rec601)→f3kdbで10bit出力→x264(10bit)の例
   avs2pipemod_0_4_1.exe -rawvideo allRGB左上-f3kdb10.avs | x264_r2184_10bit.exe  - --demuxer raw --input-csp i444 --input-depth 10 --input-res 2048x2048 --output-csp i444 --frames 2 --fps 1/1 --qp 0 --colormatrix smpte170m -o allRGB左上-f3kdb10-Rec601.mp4

 ●RGB24→x264(10bit)【--vf resize:csp=i444:16 (bgr24→yuv444p16le)】の例
   avs2pipemod_0_4_1.exe -rawvideo=vflip allRGB左上.avs | x264_r2184_10bit.exe - --vf resize:csp=i444:16 --demuxer raw --input-csp bgr --input-depth 8 --input-res 2048x2048 --output-csp i444 --frames 2 --fps 1/1 --qp 0 --colormatrix smpte170m -o allRGB左上-10bit-resize.mp4

■デコード環境と、画像の取得・比較方法

  ●環境
    MPC-HC v1.6.0.4014
    Haali Media Splitter 1.11.288.0
    ffdshow tryouts rev4371 (※1)

    ※ffdshow tryoutsは、「ビデオデコーダーの設定」の「RGB変換」で、
        ◎「手法」の「YV12からRGBへの高画質変換」のチェックを外す。
            →外さないと余計な処理が入るため。
        ◎「入力レベル」を「標準」から「自動」に変更。
            →H.264のVUIに含まれるfullrangeフラグを判定させるため。
      という設定変更をしています。
      他の設定はデフォルトです。

  ●エンコード後の画像の取得
    MPC-HCの「Save Image」でPNGとして保存。

  ●元画像とエンコード後画像の一致部分の比較
    AviUtl 0.99k2+拡張編集プラグイン 0.89pで、元画像の上にエンコード後画像を
    合成モード(差分)で合成し、フレームバッファを取得。
    差分合成により、RGB(0,0,0)となっているピクセルは、元画像と同じだと判断できる。
    スクリプト制御で、RGB(0,0,0)となっているピクセルを数えるLuaスクリプトを書き、その数を調べた。
    2048x2048の4ファイルの合計を調べ、RGB24の16777216色のうち、
    どれだけのピクセルが元と同じ色を保っているかを調べている。

■元の画像の色と同じ色を保てたピクセル数の調査結果

  ●RGBのavsファイルをそのままx264に渡してエンコードした場合

  ●avsファイルで各種プラグインによるcolorspace変換を行ってからx264でエンコードした場合

x264
bit-depth
avs  x264
option
同じ色 割合
処理概要 BT.601
or
BT.709
range output
depth
10bit Ditherで16bitに。 709 pc 16 16777119 99.999%
601 pc 16 16713766 99.622%
709 tv 16 16774667 99.985%
601 tv 16 16760115 99.898%
Ditherで16bitにした後
f3kdbで10bitに。
601 tv 10 10883930 64.873%
RGB24をそのまま。 601 tv 8 --vf
resize:
csp=i444:16
2660612 15.858%
RGB24をそのまま。 601 tv 8 2660612 15.858%
8bit Ditherで16bitに。 601 tv 16 2381956 14.198%
RGB24をそのまま。 601 tv 8 2660612 15.858%

  ●RGB24のavsを、ffmegやavconvによりYUV4:4:4(16bit)やYUV4:4:4(10bit)に変換してからx264でエンコードした場合

Tool x264の
bit-depth
Toolからの
raw出力
BT.601
or
BT.709
range 同じ色 割合
ffmpeg r38996 10bit YUV4:4:4(16bit)
(yuv444p16le)
601 tv 16731867 99.730%
YUV4:4:4(10bit)
(yuv444p10le)
601 tv 16776524 99.996%
avconv r32956 10bit YUV4:4:4(16bit)
(yuv444p16le)
601 tv 2660612 15.858%
YUV4:4:4(10bit)
(yuv444p10le)
601 tv 2660612 15.858%

■メモ

 ●x264の「--vf resize:csp=i444:16」でbgr24→yuv444p16leへの変換が行われたはずなのに
   なぜbgr24→yuv444p(8bit)した時と同じ結果になっているのかがよくわからない。

 ●「--vf resize:csp=bgr:16」としてみたが、ログではbgr24→bgr48le→yuv444p16leという
   変換を行っているように見えるものの、これも結果はbgr24→yuv444p(8bit)の時と変わらなかった。

 ●Ditherで16bitのBT.709のpcレンジにした場合でも100%にはならなかった。

 ●Ditherで16bitのBT.601にする場合、pcレンジよりもtvレンジのほうが良い結果になっている。

 ●8bitエンコードする場合、Ditherで16bitにしたものを渡すとRGB24をそのまま渡す場合よりも悪い結果になっている。

■サンプルの提供

 この記事で使った画像とは違いますが、ColorBarsをベースにした画像を
 Ditherやf3kdbを利用してエンコードするサンプルを作成しました。
 色変化のチェックがしやすいと思いますのでよろしければどうぞ。

      RGB24→10bitYUV実験のサンプルファイル

 詳細については同梱してある「説明.txt」をご覧下さい。
 一応この記事で使った「all16777216rgb.pngを4分割した画像」も入れています。

|

« Chikuzen氏のavs2pipemodとRawSourceの記事へのリンクwith変更履歴 | トップページ | FlashPlayer11.2.202.228以降で発生する問題と対処方法 »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1278146/44583608

この記事へのトラックバック一覧です: RGB24をx264(10bit)のi444で可逆圧縮し、どれだけ同じ色を保持できるか調べる。:

« Chikuzen氏のavs2pipemodとRawSourceの記事へのリンクwith変更履歴 | トップページ | FlashPlayer11.2.202.228以降で発生する問題と対処方法 »