2016年9月1日木曜日
MPEG2DecPlus その3
修正:
- RFFフラグアリのソースでupConv > 0のとき出力が壊れてたのを修正。
- 不要になったバッファの確保を削除。
JEEBサーバにある最新版バイナリへのリンクを右側に追加しましたので、ほしい方はそちらからDLしてください。
なお、今回のバグは0.0.0からすでにあったようなので、旧バイナリはすべて削除されました。
2016年8月30日火曜日
MPEG2DecPlus その2
変更内容
・idct=5(IEEE1180 reference)を倍精度浮動小数点処理に戻した(より遅くなった)。
・idct=4として単精度浮動小数点処理のLLMアルゴリズムを実装(SSE2またはAVX2使用)
0.0.0においてはとりあえず64bit化を目標にしていたため、iDCT関連は3のみをintrinsicで書き換え、5は単精度浮動小数点処理として新規で書き直し、他は全部削除という少々寂しい感じでしたが、これで少しはましになったように感じます。
今回追加した単精度LLMは従来のidct=4(64bit floating point)の替わりになるものとして追加したつもりです(コード自体はDCTFilterで書いたものとほぼ同じ)。
品質は単精度のためほんのわずかに落ちますが、それでもほぼ最高品質と言っても問題はないですし、速度は向上しています。
そしてIEEE1180 referenceは単精度にしていたのをやめて倍精度に戻しましたので、出力も従来のものと完全に一致するようになりました。(ただし、一応SIMD化はしていますが、従来のIEEE1180 referenceよりも遅いです)。
ところでDGDecodeのidctはたくさんありますが、どれを使うべきなのかをちゃんとわかっている人って、現在だとどのくらいいるのでしょうか?
かつて、idct=5に丸め込みバグがあったころは「普通は6を除いた中で一番速いもの、とことん品質重視なら4」というのが答えでしたが、5のバグが直ってからは、よくわからないという人が増えてしまったのではないかと思ったのでついでに解説しておきたいと思います。
まず1、2、3の三つは使っているCPUの命令セット以外は同じなので、スピード以外はなにも変わりません。
7(simple MMX)は1、2、3よりも少しだけ質が良いですが、スピードを落としてまで選ぶほどのものかどうかは疑問があります。
6(skal)はスピードは3に並ぶほど速いですがIEEE1180 compliantではない(実用上はともかく、規格的にはダメな実装である)ため、3が使えるCPUでは選ぶ意義はまったくありません。
4と5は品質的にほぼ等価なので、もし品質をとことん重視したいならばより速い4を選ぶべきでしょう。
以上によりSSE2がまともになったmerom(core2duo)以降のCPUであれば、3か4のどちらか好きな方ということになります。
で、品質の違いを確認する方法なんですが、ググってみた限りではなぜか「これだ」と思えるようなわかりやすいものがみあたらなかったのでこれも解説します。
src = "xxxxxxxxx.d2v" #d2vであればなんでもよい
ref = MPEG2Source(src, idct=5) #とりあえず最高品質とされる5
target = MPEG2Source(src, idct=4) #5と比較したいもの
d0 = mt_lutxy(ref, target, "x y - abs 0 > 255 0 ?", chroma="process").SUbtitle("diff>0")
d1 = mt_lutxy(ref, target, "x y - abs 1 > 255 0 ?", chroma="process").SUbtitle("diff>1")
w = BlankClip(d0, width=4, color_yuv=$FFFFFF)
StackVertical(StackHorizontal(ref, w, target), StackHorizontal(d0, w, d1))
これでこんな感じの画像が得られるはずです。今回はffmpegでエンコードした640x480のmpeg2を使いました。下半分の左側はidct=5と比較して出力が一致するサンプルは0、1でも違う場合は255に変換したもの、右側は出力が2以上違う場合のみ255で他は0に変換したものです。
自分的には出力の違いが1を超えない(右側は全て単色)で、かつ違いの出るピクセルの数が0.01%未満であれば最高品質と言っていいのではないかと思います。
出力1の違いを肉眼で判別できる人間はいませんし(もし出来るという人がいれば、それは実は人間ではないか、頭がおかしいか、ただの嘘つきのどれかです)、なにかしら軽くフィルタを一つかけるか非可逆圧縮でもしようものならば簡単に吹き飛んでしまいますので、違いなんてでようがないのです。
品質とコストの兼ね合いをどうするかは人類普遍のテーマです。
安易に遅い方が質が良いとか考えないよう注意してください。
2016年8月29日月曜日
MPEG2DecPlus
MPEG2DecPlus
事の起こりはavs2pipemodのgithubのissue trackerにmaki_rxrz氏からtypoの指摘が来ていたことです。
で、typo自体はすぐ直したのですが(バイナリはリリースしてないけど)、ついでにちょっと覗いてみたmaki氏のDGMPGDecレポジトリ(国内放送TS向け修正版)に興味が出たのですね。
「そういや64bit用のDGDecodeって、けっこう昔にJossyD氏がビルドしたやつしかないんだっけ」とか思いながら試しにビルドしてみたら、32bit用バイナリでも結構大変な目にあいました。
まずコードにいくつかNASM用のアセンブラが入っているため、VisualStudioだけではビルドできない。
さらにMASM用のアセンブラもVC6のころのMASM用に書かれているため、古いMASMを拾ってくる必要があるというものでした(数日後には最新のMASMに合わせたコードに書き換える修正が入りましたが)。
ものがMPEG2デコーダだけにソフトウェア特許絡みで面倒そうなためか、maki氏はバイナリは配布していません。
でも自ビルドするにはいささか敷居が高そうだし(もし5年前の自分だったら15分ほどでほっぽりだしてます)、こりゃ何とかしといたほうがよさそうだなぁとか思ったわけです。
で、やったことは
・アセンブラ(MASM、NASM、インラインASM)を削除(x87FPU用のASMなんて読みたくないし、MMX、MMX2、3DNow!とかもいい加減古すぎ)
・削除したASMの替わりにintrinsic(最低ラインはSSSE3以上を目安)で書き直し
・VFAPI用コードの削除(AviUtlやTMPGEnc2.5はこれなしでもavs読めるし、もういらんでしょ)
・YV16、YV24出力対応(YUY2やRGB24で出力するのはavs2.6以降ではデメリットしかない)
・MPEG2Source以外のフィルタの書き直し
といったところです。
さてここで一番問題になるのがMPEG2Sourceのポストプロセス処理(cpuとかcpu2とか)とBlindPPです。
なにが難しいのかといえば、これはTrbarry氏がメイン処理部分をすべてインラインアセンブラのみで書いていてCのコードを残していないため、なにをやっているのかさっぱりわからないからです。
DctFilterもそうでしたが、あの人のコードはいつも参考になりません。
とりあえず半日ほど格闘してみましたがどうにもCに書き直すだけでも大変そうで埒があかないので、諦めて全部捨てることにしました。
かくして64bitでビルドするための障害はすべて消え去ったので、ついに昨日、0.0.0としてファーストリリースについにこじつけることができました。
で、バイナリですが、JEEB氏が再配布してくれることになったため、右のほうのリンク先から入手できます。
現状、ソフトウェア特許を認めていないEU圏のフィンランド人がドイツだかフランスだかにあるサーバで配布してるので、特許料請求とかも関係なくって安心ですね。
まあ、その特許もあらかた切れてるらしいので日本やアメリカで配っても大丈夫なのかもしれないけど、本当に大丈夫なのか調べるのも面倒ですし…。
2016年8月18日木曜日
DCTFilter その4
バイナリ
追加・変更等
・avisynth2.6用のコードのバグを修正。
・avisynth+の追加フォーマットに対応。
avs2.6のみで使われるコードにバグがあったのを修正するついでにavs+の10/12/14bitフォーマットにも対応させました。
もともと内部処理はこれを見越してのfloat演算なので、入力クリップのbit深度とRGBかYUVかを判定するコードを追加するだけでした。
さて、このフィルタはMT_NICE_FILTERとして使えるように書いたつもりです。
そしてユーザー側で特にMT modeを設定しない限りはMT_NICE_FILTERとして設定されるようにもしています。
ところがDeblock_QEDにこれを使ってマルチスレッドで実行すると映像が壊れることがあるという報告を一件受けました。
で、試しに手元のサンプル映像に掛けてみたのですが、特にそんな様子もありません。
そもそもMT_NICE_FILTERというのは、avisynth+がマルチスレッドで動かそうとする際に特に障害となるような要素を持っていないだけの、ただのシングルスレッドで動くフィルタのことです。
マルチスレッドで動かしているのはavisynth+のほうなんですから、バグるなら報告先が違うような気がするんですが…?
あと、不具合が出るソースのサンプルもスクリプトも実行環境の説明も何もなしにただバグると言われても正直困ります。
再現可能な情報の提供がなければ動きようがないのです。
逆に再現率が高く再現方法も手軽なものであれば、そのバグは大抵すぐに直ります。
というわけで、バグを見つけられた方はなるべく再現方法も教えてください。お願いします。
追記:報告者によると、これのほかにavs+やらいろいろ更新したら再現しなくなったそうです…まあ、そんなところだろうとは思ってたけどね。
2016年8月17日水曜日
最近のAvisynth+を使う場合の色々について
なお、この記事の内容はあくまでも現時点(r2161)でのものですから、今後どのように変わるか(あるいは変わらないか)はわかりません。
・SetLogParams
SetLogParamsはr2064で追加されたログ機能です。
avisynth+を実行中に発生した色々な情報を出力します。
SetLogParams(string file, int log_level)fileはログの出力先の指定で、"stderr"だと標準エラー出力、"stdout"だと標準出力、 "D:\foo\bar\avslog.txt"のようにファイル名にすればファイルに出力されます。
log_levelは出力するログの範囲の指定で、LOG_DEBUGなら詳細なすべてのログ、LOG_INFOならば普通のログ、LOG_WARNINGならば警告及びエラーのみ、LOG_ERRORならばエラーのみを出力します。
この機能によりAvisynth+本体及びプラグインによって発生した疑わしい挙動や不具合が大変わかりやすくなり、バグレポートしやすくなりました。
今後コマンドラインのツールを使う場合はSetLogParams("stderr", LOG_INFO)、AviUtlやVirtualDubのようなGUIツールと併用する時はSetLogParams("出力ファイル名", LOG_INFO)をスクリプトの先頭になるべくつけるようにすることをお薦めします。
・SetMemoryMax
こちらはavisynth2.5の頃からのお馴染みですが、どれくらいに設定しているでしょうか?
SetMemoryMax(int mem)avisynth+は規定値として32bitの場合(より正確には物理メモリより仮想メモリのほうが少ない場合、つまり64bitOS上で32bit版を使う場合)は128MB、64bitの場合(というか物理メモリより仮想メモリのほうが多い場合)は1GBをavisynth本体が使うメモリ量の上限として物理メモリを確保しようとします。
よってこれ以上を使うことが予想される場合、もしくはもっと少なくてもよい場合を除けば、これはスクリプトに書く必要はありません。
また重要なのは、このメモリ上限はあくまでもavisynth+本体が使用するメモリ量であり、プラグインフィルタが使うメモリ量ではないということです。
もしあるプラグインが中間バッファの確保にmallocやstd::vectorを使っても、その分はカウントされません。
Avisynth+には新たにバッファプール機能が追加されたため、この機能を使えばプラグインのメモリ使用量もavisynth+本体で管理することが可能になりましたが、実際に使っているプラグイン作者は現時点では私くらいしかいません(特に問題は見当たらないのですが、一応実験的な機能ってことになってますし)。
よって下手に大きな上限値を設定すると、プラグインのほうでメモリ不足を起こす可能性が出てきます。
で、あるスクリプトの実行時にどれくらいメモリを必要とするかは、使用するフィルタ及びソースの解像度等に依存するわけですが、もし設定された上限値では足りない、若しくはもう少しあったほうがより円滑に処理出来る場合は、先ほどのSetLogParamsによるログで教えてくれるようになりました。
というわけで、決め打ちに走るのもまあ悪くはないかもしれませんが、適切な量を調べてみるのもいいのではないかと思います。
とくにAviUtlと併用する場合はアプリケーション側も32bitなのにメモリ食いまくりますんで、絞れるところは絞るべきでしょう。
・SetFilterMTMode
Avisynth+の目玉機能の一つはフレームレベルでのマルチスレッドですが、皆さん使っていますでしょうか?
私は(ここ数年はエンコはせずにコード書くだけの人なので)あまり使ってません。
とりあえずこのフィルタはMT_NICE_FILTERだ、これはMT_MALTI_INSTANCEじゃないとダメだ、とあれこれやるわけですが、ここで重要なのは"DEFAULT_MT_MODE"をどれに設定するかです。
現時点ではDEFAULT_MT_MODEは3(MT_SERIALIZED)以外ありえません。
"DEFAULT_MT_MODE"は、MT modeが設定されていないすべてのフィルタに影響するため、下手に2(MT_MALTI_INSTANCE)などにしようものなら安全な実行はまったく保証されなくなります。
そもそもいままで書かれてきたavisynthプラグインのほとんどはシングルスレッドでの実行を前提としているものが多く、また処理内容的にもマルチスレッド化はスライスレベルでしか実現不可能なものもあります。
このページには"mode 3 is evil."なんて書かれていますが、時間軸IIRフィルタを邪悪呼ばわりするとか、正直頭がおかしいんじゃないかと思います。単にちょっと前までのavisynth+MTにとって都合が悪かったものをそうやってくさしてるだけです。
本当に邪悪なのはmode 2です。
mode 2で動かせるフィルタは、すべてmode 1で動かせるように改変可能なフィルタです。
でも実際にこれまで書かれてきたフィルタを全部改造していくのはちょっと無理なんで、フィルタクラスを複数インスタンス化しそれらを同時に動かすという力技でごまかしているのがmode 2の実態です。
ちなみにmode 2というのは、avisynthMTのSetMTMode(2)と基本的に同じものです。Avisynth+ではキャッシュ機能も改良されたのでメモリ使用量も減って、かなり安定度も上がりました(が、それでも安全とは言いきれない)。
前回記事のコメントで私がなかなかScriptClipの不具合に気づかなかったのは、SetFilterMTMode("DEFAULT_MT_MODE", MT_SERIALIZED)と書かれたavsをオートローディングフォルダに突っ込んでるのを忘れてたからなんですね。
と、だらだらと書いてみました。
もし参考になった方がいましたら幸いです。
2016年8月14日日曜日
avs2pipemod その22
ver.1.1.0になります。
追記:バグ1件見つけたので1.1.1を上げました。
バイナリ
変更/追加
- avisynth+の追加色空間のサポート
- y4mbitsオプションの削除
- filtersオプションの追加
昨晩、avisynth+にあらたに10/12/14bitおよびPlanarRGBが追加されました。
これを見てもらえば、だいたいどんな感じになったのかなんとなくわかってもらえるのではないかと思います。
いや、もう、なんというか、やりすぎじゃありませんかね?
14bitとかYUV420でアルファに対応とか、基地外沙汰というかFFmpeg脳というか、まじで勘弁してほしいんですが。
2016年8月10日水曜日
alloca vs vector
avisynthプラグインの書き方は人それぞれですが、一つの指標として次のようなものがあります。
AviSynth Plugin Writing TipsこれはAviSynth Wiki内に置かれたAvisynth+特設ページ内の記事ですが、特に書き慣れていない人、これからなにかしら書いてみたい人は一度は目を通しておくことをお勧めします。
- 例外は基本的に使わない。
- 自分でマルチスレッド処理を実装しないこと。
- 使用するヘッダ(avisynth.h)はAvisynth+の最新のものを使うこと。
使う場合は発生時の処理もプラグインdll内で完結させる。上流(avisynth本体)に投げる場合はIScriptEnvironment::ThrowError()を必ず使うこと。
特に最近のAvisynth+は単にGetFrame()を同時に複数実行するレベルではなく、全体的なバランスをとりつつキャッシュコントロールするレベルまで進歩しています(AvisynthMTとThreadRequestを両方実装したような感じかな)。 追加フィルタレベルでマルチスレッド化なんてやってもオーバーヘッドが増えるかデッドロック起こすだけで無駄に終わりますし、特にOpenMPの使用は(Avisynth+では)最悪手です。 シングルスレッドだとC++のみでは性能が出ない場合はSIMDを使うかGPUプログラミングに行くしかありません。
Avisynth+のヘッダはAvisynth本家の最新ヘッダと完全互換を謳っていますし、実際にそうなっています。特に64bit化を考えるならAvisynth+のものを使うしかありません。
で、それに続いてWriting better AviSynth pluginsという記事があります。
- YUY2用のコードは書かない
- メイン処理用関数はクラスメンバーにしない
- memcpyの再実装はしない
- Y,U,V各プレーンで同じ処理をする場合にコピペはしない
こちらも概ね正しいですが、一番最後のDon’t be afraid of allocaだけは参考にしない方がよいようです。
最近のコンパイラ(確認した限りではVS2013以降)であればstd::vectorを使うべきあり、もはやallocaを使う意義はまったくありません。
実際に私はallocaをstd::vectorに置き換えてみましたが、スピードはほぼ等速か、むしろstd::vectorのほうがほんの少し速かったです。
わざわざ初期化したり最後に個々の要素を開放したりは手間になるだけです。
ちなみにstd::vectorではなくnew/deleteで配列の確保/解放をしてみると、これも変わらないか若干vectorのほうが速い感じになりました。
どうやらC++においては動的配列の場合、_aligned_malloc/_mm_malloc以外はstd::vectorにしておくのが間違いがないようですね。
2016年8月4日木曜日
DCTFilter その3
もうリンクはバイナリだけでいいかな。
右のほうにgithubへのリンク付けておいたので、ソースコードに興味のある物好きな方は適当に漁ってください。
バイナリ
0.4.0です。
4x4DCTも出来るようにしました。
あとplaneのWidth/Heightが8の倍数でない時でも、4の倍数であれば8x8DCTができるようにしました。
単に余った右端及び下端は4x4DCTで済ませてるだけです。
いや、1920x1080のYUV420でベンチマーク取ろうとしたところで出来ないことを思い出したので、つい勢いでやってしまいました。
これだと都合が悪い場合は、これまでのようにpadding/cropでもして下さい。
2016年8月2日火曜日
DCTFilter その2
いろいろ細々と最適化とかやってたら0.3.0になりました。
DCTFilter
バイナリ
- 最適化を進めた結果、単精度浮動小数点処理でもSSE4.1(int32->uint16の高速変換に必要)が使えれば、オリジナルのDctFilter(MMX/ISSE/SSE2?で整数処理)とほぼ同等のスピードで動くようになりました。AVX2/FMA3が使えるCPUならこっちのほうが速いです。
- DCTFilterD()を追加しました。
- avs2.6もサポートするようになりました。
書いてみてから改めて調べてみると、このフィルタは結構面白い使い方が出来るようですね。
なんだかお気に入りになりそうです。
2016年7月31日日曜日
DCTFilter
DCT/iDCTはよくわからんのでその時は「後でね」とごまかしてたんですが、数日前に今度はよく知らない外国の人からメールで「64bit版書いてよ」とリクエストが来てしまいました。
ちょうどAvisynth+のレポに送ったPRが3つも貯まったまま放置されてる状態なので(ultimははよコミットなりリジェクトなりしろよ)、気分を変えようと書いてみることにしました。
とりあえずアルゴリズムは簡単に実装できそうでサンプルも豊富なLLMで、いろんなbit深度にいちいち対応するのもめんどいので整数近似はやらずに浮動小数点で処理することに決定。
(オリジナルのコードはxvidから持ってきたわけのわからんASM使ってるのでパス)
で、実際に書き始めたら二日ほどでなんとか出来上がりました。
ソースコード
バイナリ
なお、これはAvisynth+MT専用です。
Avisynth2.6では動きません。
それにしても毎度のことながら、一番時間かかるのがREADME書くことなのはなんとかならないものかしら…。
2016年7月24日日曜日
avs2pipemod その21
バージョン1.0.3になります。
ソースコード
バイナリ
- メモリーリーク?の修正
- バージョンリソースを追加
つい先日のAvisynth+の更新でログ出力機能が追加されました。
スクリプトにSetLogParams("stderr", LOG_INFO)と書いておけば、標準エラー出力にログが出るようになります。
"stderr"を"stdout"にすれば標準出力に、"ファイル名"とすればファイルに保存されます。
で、さっそく使ってみたところ"WARNING: A plugin or the host application might be causing memory leaks."とか表示されやがるんですな。
どうやらプラグインと違ってアプリケーションでは、PClipのインスタンスをクラスメンバーにしている場合は自分でデストラクタを呼ばないとこうなるらしい。
どのみちすぐexitしてしまうので実害はないとは思いますが、気持ちいいものでもないので修正しました。
あと、今回からバージョンリソースを追加したので、Explorerでバージョンが分かるようになりました。
VS2015だとタダでリソースエディタが使えるのを思い出したので付けてみたわけですね。
プラグインとかはどーするかな…。
2016年7月22日金曜日
avs2pipemod その20
バージョンは1.0.2になります。
ソースコード
バイナリ
- infoで表示されるv:durationの計算が間違ってたのを修正。
- infoでavisynthのVersionNumberの他にVersionStringも表示されるようにした。
本来durationの計算は num_frames * fps_denominator / fps_numerator ですが、これを num_frames * fps_numerator / fps_denominator に間違えてました。ごめん。
もう一つの変更点について
その18で書き忘れてたのですが、1.0.0からavs2pipemodには'-dll'というオプションが追加されました。
これは複数のavisynth.dllを使い分けるために用意したものです。
たとえば
avs2pipemod -info -dll="C:/hoge/fuga/avisynth.dll" script.avsとやれば、avs2pipemodは'C:\hoge\fuga\'にあるavisynth.dllを使います。
あと、うちのC:\Windows\SysWOW64には'AviSynth.dll'の他に'AviSynth.dll_official260.esc'とか'AviSynth.dll_official261a.esc'なんてファイルも存在したりするのですが、これも
avs2pipemod -benchmark -dll="avisynth.dll_oficial261a.esc" test.avsのようにすれば、そちらのDLLを使うようになります。
-dllを未指定の場合は今まで通り、Pathの通ったところにあるAviSynth.dllを使います。
で、VersionNumberだけだとどれも2.600としか表示されないのでもうちょっとわかりやすくする必要があったのですね。
まあ、そういうことです。
2016年7月18日月曜日
avs2pipemod その19
ソースコード
バイナリ
変更点
- rawvideo及びy4m出力の際のチェックが間違っていたのを修正
staxripの中の人からバグレポ貰ったので直しました。
なんつーかたいへん間抜けかつありがちなバグでした。
1.0.0を使ってる人は更新してください。
2016年7月10日日曜日
avs2pipemod その18
ソースコード
バイナリ
変更点
- avisynth_c.hを使うのをやめてavisynth.hを使うようにした。
- C99をやめてC++で書きなおした。
- VisualStudio2015以降(または新しめのインテルのコンパイラ)でしかビルドできなくなった。
- avisynth2.5xのサポート終了。
- WindowsXPのサポート終了。
- x264bdとx264rawが使えなくなった。
- Avisynth+の16bit/32bitフォーマットに対応した。
- Y4M出力でffmpegの拡張を使えるようにした。
上記のようになんかガラッと変わったように見えますが、Avisynth+MTの最新版を使っている人以外にはどうでもいい変更ばっかでもあります。
まあ、すべてはavisynth_c.hが悪いんです。
というわけで、Avisynth+MTの新しいの使ってるよって人は更新してみたらいかがでしょうか。
もしx264bdとx264rawもまだいるよって人はパッチ書いて送ってね!
2016年7月6日水曜日
いろいろ更新
で、いろいろ変更が入ったんですが、本家2.6.1の更新を取り込んだ分でAvisynth+のほうだけAPIブレイクが起こり、自分が公開しているプラグインのうちの大部分が影響をもろに受けてしまうことがわかりました。
なんとロードするだけでavisynth全体がまともに動かなくなってしまうという…。
というわけで以下のプラグインを更新しました。
RawSource26
PlanarTools
yadifmod2
TMM2
CombMask
TCannyMod
VapourSource
それぞれリリースページに飛びますので、Avisynth+MTを使ってる人は最新のやつに更新してください。
なお、本家Avisynth2.6しか使ってない人は別に更新する必要はありません。
それにしてもとうとうAvisynth+も8ビットの枠から飛び出してしまいました。
プラグイン書く人としては10bitだの16bitだのfloatだのはどうやって出力を検証したもんだかで色々頭が痛いのですががが…。
2016年5月27日金曜日
CombMask
ソースコード
バイナリ
このフィルタ、元々は3年くらい前に書いてそのままバイナリ配布とかせずにほっぽってたものなのですが、誰か別の人がビルドして配布していたようです。
書いたきっかけはたしかvapoursynthのVIVTCがオリジナルのTIVTCと違ってedeintオプションを使えないし、かといってTDeintとの連携もできない残念な仕様だったので、少しはましになるかと思ったんでしたかね。
なんでavisynth版も書いたかといえば、avisynthプラグインのほうがテストしやすく、サポートしているフォーマットも少なくて書きやすいからです。
まずavisynthプラグインを書いてみて、処理の全体的な流れや具体的な内容等のロジックを決めてある程度テストしてからでないと、なかなかvapoursynthプラグインは書けません。
で、結局作りこまずにそのまま…というのが真相なんですが、このたび誰かさんが配布してたバイナリが消えちゃったので自分のGithubレポのほうでバイナリ配布してくれないかとお願いメールが来まして、正式に配布することにしたついでにコードの見直しや機能追加もしました。
具体的には
・Avisynth+MT対応で、SetFilterMTModeが使える環境では自動的にMT_NICE_FILTERとして登録されます。
・AVX2も使えるようにしました(メモリアライメント等の都合上、Avisynth+MTのみ)。
・縞検出にTIVTC等のmetric1も使えるようにしました。
・コードがちょっと綺麗になりました(と、自分では思っている)。
といった感じです。
縞検出のmetric1は、そもそもTIVTC以前のdecombパッケージやMaskTools1のCombMask()で使われているものなんですが、はっきりいってインタレ縞検出用だと誤爆しまくって使えないんじゃないかと思います。
しかし、世の中には単に縦方向のみのノイズ検出フィルタとしていまだにMaskTools1を使っている人がいるようなので追加しました。
MaskTools1のはSIMD化されてないのでクソ遅いですし。
MaskTools版の
CombMask(clip, thY1=x, thY2=x, Y=3, U=1, V=1)
と、こっちの
CombMask(clip, cthresh=x, mthresh=0, chroma=false)
で、同じになります。
UやVだけに使いたい場合はUToY8/VToY8を併用してください。
それにしてもAVX2、なかなか速くなりませんね(HaswellではSSE2比120%弱くらいかな)。
SSE2がPen4で登場してCore2でまともになるまでに6年くらいかかったので、5年後くらいには180%くらいにはなってるんじゃないかとは思うんですが…。
2016年5月21日土曜日
TMM2
ソースコード
バイナリ
※ TMM2_avx2.dllはAVX2が使えるバージョンです。Nehalemとかだと多分動きません。
※ aviisynth+ではMT_NICE_FILTERとして使えます。なお、FilterModeはスクリプト初期化時に自動的に登録されますのでSetFilterMTMode()は必要ありません。
書き始めたのは結構前なのですが、8割くらいできたところで飽きてほっぽってたら某所に催促らしきものが書かれてたのでとりあえず動くようにしてみました。
元はC++(というかほぼC)のみのコードだったので、SSE2/AVX2を追加してみたら4倍弱速くなりました。
ほんとはもうちょっと早くなると思ってたんですが、フィールド別に作られた2つのモーションマスクを一つに組み立てる最終工程で大幅にスピードダウンしてしまうので、それほどでもなかったようです。
lengthを10固定にすれば多少は改善の余地はある?
あと、最後の工程で出力がオリジナルのTMMとちょっと変わってしまっているようです。
どこで変わってるのか何度もコード見直してみたんですがよくわからないし、そもそもそれでどれくらい影響が出るのかもさっぱりわかりません(エンコとかもう数年やってないし…)。
とりあえず公開しておきますので、もし不具合見つけたら教えてください。
つーか、だれかどこで違いが出てしまうのか教えてお願い…。
2016年5月11日水曜日
vsavsreader その7
2016年5月7日土曜日
VapourSource その2
2016年4月9日土曜日
Avisynth+のビルド
というかCMakeほとんど使わないので書いておかないと(また)忘れそう。
用意するもの
・Git for Windows(最新版は2.8.1)
・CMake(最新版は3.5.1)
・VisualStudio Community 2015
・githubのアカウント(パッチ書いてPull Request送りたい人だけ)
インストール
1. Git for Windowsをインストール
インストールの際は必ずPATHを通しておくこと(Use Git from Windows Command Promptを選択すればよい)。
ここでUse Git from Git Bash onlyを選んでるといろいろCMakeのほうでメンドクサイことになる。
Configure the line ending conversionは必ずCheckout as is, commit as isにしましょう。他を選ぶやつは何考えてるのか理解できんわ。
ちなみに筆者は普段はMSYS2のGitを使っているのですが、それでも別にGit for Windowsをこのためだけに入れております。
Git for WindowsがないとAvisynth+のビルドに必要なファイルが生成できないのです。
2. CMakeのインストール
特に注意するところはなかったはず。
デフォルトの選択肢のままでよかったと思うが、一応ちゃんと選択肢等の説明は読むこと。
こちらはPATHを通したりする必要は特にありません。
3. VisualStudio Communityのインストール
VC++が使えればあとはお好きなようにしてください。
ただし調子こいてあれこれ入れるとサイズは40GB超えて、かかる時間もとんでもなく増えるそうですよ。
ローカルにGitレポをcloneする
最近はAvisynth+の公式のほうは動きがぱったり止まってるので、pinterf氏のほうをcloneしたほうがよさそうです。
あなたがなにかしらパッチ書きたいならhttps://github.com/pinterf/AviSynthPlusを自分のアカウントでforkしてからsshでcloneしましょう。
sshの鍵作成とかgithubへの登録とかは自分でググって調べてね。
自ビルドだけなら、適当なフォルダに移動して右クリック -> Git Bash Here->
'git clone https://github.com/pinterf/AviSynthPlus.git' でいいです。
cloneが終わったらpinterf氏の変更を取り込みます。
以下の順にコマンドを打ちましょう
'cd AviSynthPlus'
'git remote add pinterf https://github.com/pinterf/AviSynthPlus.git'
'git fetch pinterf'
'git merge --no-ff pinterf/MT-pfmod'
これで手元の'master'ブランチに全変更がmergeされました。
ソリューション/プロジェクトの作成
ソースコードの準備が出来たら次にVisualStudio用のソリューション/プロジェクトファイルの作成です。
まずスタートメニューからcmake-guiを起動します。
次に'Where is the source code:'にcloneしたレポジトリを指定し、'Where to build the binaries:'に好きな場所を指定します。
自分はこんな感じです。
'Where to build the binaries:'で指定するフォルダは存在しなければcmakeが自分で作ります(作るか別の場所にするかあとで聞いてくる)。
上記2つの指定をしてから左下のほうのConfigureボタンを押すとこんなウィンドウが出てくるので
'Specify the generator for this project' のところを 'VisualStudio 14 2015' にします。
あとはそのままで'Finish'を押しましょう。
すると
こんな画面になるので
CMAKE_GENERATOR_TOOLSETのところをクリックしてv140_xpをv140に変更します(XPはさっさと滅ぶべきです)。
そしてもう一度Configureボタンを押して赤いのが白くなったらGenerateボタンを押せば終わりです。
VisualStudioでビルド
さきほど'Where to build the binaries:'で指定したフォルダを開くと中に色々ファイルやフォルダが出来ています。
その中のavs_coreフォルダを開き、中にあるAvsCore.slnをダブルクリックすればVisualStudioが起動します。
あとはソリューションエクスプローラーでAvsCoreのビルドを実行すればいいです。
なにかしらビルド中にやたら警告が出るとは思いますが、エラーになっていなければ大丈夫です。
64bit用もほしければ構成マネージャでプラットフォームを追加してください。
もし64bit用バイナリをビルドしようとしてLNK1112のエラーが出て失敗した場合は
ソリューションエクスプローラー -> AvsCore -> 'プロパティ' -> 'プラットフォーム(p):'がx64になっているのを確認 -> リンカー -> コマンドラインと進みます。
で'追加のオプション'のところに/machine:x86とあったら、それを消して適用 -> もう一度ビルドすればいいです。
大雑把ですが、はまりどころはそれほどはないはず…CMakeめんどくさいんだよバカ…



