22 Mar 2014

avs制御用ユーザー定義関数

あまり使いドコロのない小技を幾つか
ただしavs+を想定

・関数内でグローバル変数を宣言し,その関数が有効である時のみ別の関数を有効にする.
そのままです.コメントしたりアンコメントしたり,はたまたし忘れたりするのが嫌になったので
e.g.
global CHECK_PC = false

trim_wrapper( 4200, 12899 )

if( CHECK_PC )
{
    check_pulldown_cadence( dominance=0 )
}

...

function trim_wrapper( clip src, int start_frame, int end_frame )
{
    global CHECK_PC = true

    return src.Trim( start_frame, end_frame )
}
trim_wrapperを有効にしている場合のみプルダウンパターンのチェック用関数が有効になります.
注意すべきなのはavsは変数の宣言のみをし初期化しないということができず,必ず値を代入する必要が有ることです.そのため初めにfalseを代入してグローバル変数を宣言しておく必要があります.(まあ別にbooleanである必要はないですが.)
そうか,
if( Defined( foo ) )
{
    if( foo )
    {
        somefilters()
    }
}
としてもいいです.
私は全てのグローバル変数を初期化するようの関数を作って初めに初期化してます.(初期化だけで何行もかけたくないので)

・プログラムごとに処理を分岐
これは GetProgramName() を使えばいいだけなんですがもうちょい使いやすく.
GetProgramNameはスクリプトを読み込んでるプログラム名をstring値として返すフィルタです.
ただ,場合によって".exe"が付いてる時と付いてない時が考えられることとどちらかと言うとbooleanで値をくれた方がスクリプトが煩雑にならないので個人的にありがたいです.
そこで以下の様な関数を作成.
function is_program( string "program_name" )
{
    Assert( Defined( program_name ), "is_program: program_name shoul be defined!" )
    get_name           = GetProgramName()
    get_name_no_bslash = str_replace( get_name, "\", "/" )
    rev_name           = RevStr( get_name_no_bslash )
    slash_pos          = FindStr( rev_name, "/" )
    if( slash_pos != 0 )
    {
        no_dir_name = RightStr( get_name_no_bslash, slash_pos - 1 )
    }
    else
    {
        no_dir_name = get_name_no_bslash
    }
    str_length  = StrLen( program_name )
    no_ext_name = LeftStr( no_dir_name, str_length )
    result      = StrCmpi( no_ext_name, program_name )

    return result == 0 ? true : false
}

function str_replace( string org, string from, string to )
{
    tlen = StrLen( to )

    ret = org
    pos = FindStr( ret, from )
    while( pos != 0 )
    {
        olen = StrLen( ret )
        lstr = LeftStr( ret, pos - 1 )
        rstr = RightStr( ret, olen - pos - tlen + 1 )
        ret  = lstr + to + rstr
        pos  = FindStr( ret, from )
    }
    return ret
}
引数に取ったプログラム名(.exe無し)のstring値とスクリプトを読み込んでるプログラム名が一致すればtrueを,そうでなければfalseを返します. 大文字小文字の違いは無視します.
e.g.
IS_A2PM = is_program( program_name="avs2pipemod" )
IS_X264 = is_program( program_name="x264"        )
IS_APM  = is_program( program_name="avspmod"     )
global USE_PIPE = false
if( IS_A2PM && !USE_PIPE )
{
    detect_combed_frame( log_file=LOG_COMBED_FRAMES, cthresh=128, mthresh=8, MI=10 )
    check_fullrange( log_file=LOG_FULL_RANGE )
    detect_scene_change( log_file=LOG_SCENE_CHANGE )
}
上記の例ではavs2pipemodを使ってなおかつUSE_PIPEがfalseの場合のみコーミング検出,レンジ判定,シーンチェンジ検出の関数を有効にします.
私はデバッグ用の処理をAvsPmodで開いてる時のみ有効にしたりhigh bit-depthで出力する時x264で開いてる時のみ最後に Dither_out()入れるようにしたりして使ってます.
あとWriteFile系の処理を入れてる場合,avs+のMTが有効だと正しく処理されないのでavs2pipemodで開いてなおかつUSE_PIPEがfalseの時は自動的にPrefetchのthreadsを0にしてその代わりLWLibavのthreadsを8にしたりその逆をしたりしてます.結構便利.
ちなみにProgramName.dllの64bit版バイナリは以前某掲示板でリクエストが有ったのでupしたことがあります…

・avsスクリプトと同一ディレクトリにある同名のソースファイルを自動で読み込む.
いちいちソースフィルタの引数を変えるのが面倒なのでソースファイルの名前はavsファイルと同じにして同一ディレクトリに配置し自動的に読み込むようにします.
D:\
 |- encode
     |- hogehoge.avs
     |- hogehoge.ts
     |- hogehoge.wav
みたいな感じでファイルを配置

function get_src_path( int "src_plugin" )
{
    src_plugin = Default( src_plugin, 0 )

    ext_length  = 4    /* 4: .avs */
    str_length  = StrLen( ScriptName() ) - ext_length
    no_ext_path = LeftStr( ScriptName(), str_length )
    video_ext   =   src_plugin == 0                      ? ".ts"  \
                : ( src_plugin == 1 || src_plugin == 2 ) ? ".dgi" \
                                                         : Assert( false, "get_src_path: invalid src_plugin!" )
    audio_ext   = ".wav"
    global video_path = no_ext_path + video_ext
    global audio_path = no_ext_path + audio_ext
}
get_src_pathを実行するとaudio_pathとvideo_pathのグルーバル変数が宣言される.
上記は映像にLWLibav/DGSource/DGSourceIMを使用することを想定.音声はfawを想定.
この辺は自分の好きな様に変えればいいです.

・avisynthが32bitか64bitかによって分岐
function is_x86_64()
{
    ver_str = VersionString()
    ver_str = LeftStr( RightStr( ver_str, 4 ), 3 )

    return StrCmpi( ver_str, "x64" ) == 0 ? true : false
}
64bitならtrueを32bitならfalseを返します.
上記のget_src_pathと合わせた使用例.
SRC_PLGN = 0
get_src_path( src_plugin=SRC_PLGN )
if( Exist( video_path ) )
{
    video_clip = SRC_PLGN == 0 ? LWLibavVideoSource( video_path, threads=lw_threads, dr=true )            \
                                 .Crop( 0, 0, 0, 1080, align=true )                                       \
               : SRC_PLGN == 1 ? DGSource( video_path )                                                   \
                               : ( !is_x86_64() && SRC_PLGN == 2 ) ? DGSourceIM( video_path, engine=1 )   \
                               : (  is_x86_64() && SRC_PLGN == 2 ) ?                                      \
                                 Assert( false, "Script Setting: DGSourceIM is available only for x86!" ) \
                               : Assert( false, "Script Setting: invalid SRC_PLGN value!" )
}
else
{
    Assert( false, "Source File: " + video_path + " does not exist!" )
}
if( Exist( audio_path ) )
{
    audio_clip = WAVSource( audio_path )
}
else
{
    Assert( false, "Source File: " + audio_path + " does not exist!" )
}

※2014/04/08追記
b20からDGDecIMも64bitで使えるようになりました
---追記ここまで---

avs+はif文が使えるのでこんな感じの関数とか使えばテンプレートを上手くまとめられまする.
まあ自分しか見ないものを整形して何になるんだって話ではあります…


※2014/06/19 追記
is_program を更新しました.bat 以外のスクリプトを用いてエンコードを実行した時により確実に判別できるようになりました.
---追記ここまで---

No comments:

Post a Comment