2012年4月30日月曜日

AvsReader その5

更新しました。

AvsReader-0.4.1.zip
https://github.com/chikuzen/AvsReader/

*新機能: d2vの読み込みに対応。

だいたい終わりとか言いながら、同じ日に二度目の更新…。
早い話がavsを書かなくてもd2vをそのまま読めるようにしました。
DVD2AVI/MPEG2Dec3はupConvオプションがないので、非対応です。

追記:奇数解像度のRGB入力を壊してたので上げ直しました。

AvsReader その4

更新しました。

AvsReader-0.3.0.zip
https://github.com/chikuzen/AvsReader/

* 新機能: adjust_audio_length
自動的に内部でTrim(0, 0)を追加することで、映像と音声の尺を合わせます(デフォルトは有効)。

* widthが奇数なYV24/Y8の読み込みを変更
その2で書いたBT.709での映像崩壊を避けるため、右端のピクセルをコピーして偶数になるようにした。

これで、このプラグインでやれそうなことは、だいたい終わったかな。

追記:
widthが奇数なYC48での問題はAviUtl側の不具合ということでした(KENくん氏のお返事より)。
0.99k3か0.99lで直るそうなので、直ったらもとに戻すつもりです。

AvsReader その3

更新しました。

AvsReader-0.2.0.zip
https://github.com/chikuzen/AvsReader/

* dither hack(interleaved format/16bit)のサポートを追加

使い方等はreadmeを読んで下さい。

16bitYUV->YC48変換は結構適当ですが、
 輝度は4096(16<<8) -> 0、60160(235<<8) -> 4096
 色差は4096(16<<8) -> -2048、61440(240<<8) -> 2048
になるようにしています。

2012年4月29日日曜日

AvsReader その2

更新しました。

AvsReader-0.1.1.zip
https://github.com/chikuzen/AvsReader/

* widthが奇数なRGBの読み込みを修正。
* YV24/Y8なクリップはYC48に変換するように変更。
これにより奇数解像度にも対応(したつもり)。

YV24/Y8->YC48はBT.601限定です。
widthが奇数のYV24なクリップを読み込んで、AviUtlの色変換設定の入力をBT.709にすると、何故か表示が崩れます。
入力設定がBT.601だと問題ないので、多分AviUtl側の問題だとは思うのですが…どうなんだろ?

2012年4月28日土曜日

AvsReader

AviUtlは0.99k以降、内蔵のAVI File Reader(vfw) でavsを読めるようになりましたが、それとは別に新しく入力プラグインを作ってみました。

AvsReader-0.0.2.zip
https://github.com/chikuzen/AvsReader/

VFWを使わないでavsを読める入力プラグインは他にDirectShow File ReaderとDGMPGDecのD2V/AVS Readerがありますが、avisynth.dllを直接叩くものは多分これだけでしょう。
まあ、中身はavs2pipemodでやってることとたいして変わりませんけど…。

追記
無音のavsを読ませるとAviUtlが固まるのを修正しました。
0.0.1をすでにDLしてしまった物好きな方(5名ほどいるらしい)は、0.0.2を落としなおして下さい。

2012年4月8日日曜日

xorshift

アルゴリズムの勉強とかしてると、試しに書いてみたコードを走らせるためにたくさんのサンプルデータが必要になる。
で、標準関数のrand()を使って要素数1000個とか10000個とかの配列をでっち上げたりしていたわけですが、ここで問題にぶち当たりました。
C言語のrand()は0以上RAND_MAX以下の擬似乱数を発生させるわけですが、mingw-gccだとこのRAND_MAXの値が0x7fff(32767)しかありません。
これではもっと大きい数を扱いたい場合に色々と不便なので、「もっとよい乱数生成関数はないかいな」と探してみたところ、xorshiftというのがなかなか良さそうです。

参考:良い乱数・悪い乱数

なんでもやたら速いうえに周期が128bitもあるそうなので、uint64_tな範囲でも問題なく扱えそう。

というわけで書いてみました。
/* xorshift.h*/
#ifndef XOR_SHIFT_H
#define XOR_SHIFT_H

#include <stdint.h>

uint64_t *srand_xs64(void);
uint64_t rand_xs64(uint64_t *x);
void close_xs64(uint64_t *x);

#endif
/* xor128.c*/
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include "xorshift.h"

uint64_t *srand_xs64(void)
{
    uint64_t *x = (uint64_t *)malloc(sizeof(uint64_t) * 4);
    if (!x)
        return NULL;

    uint64_t s;
    do {
        s = (uint64_t)(time(NULL));
    } while (!s);

    *x = (s << 32) | s;
    *(x + 1) = (*x << 8) | ((*x & 0xff00000000000000) >> 56);
    *(x + 2) = (*(x + 1) << 8) | ((*(x + 1) & 0xff00000000000000) >> 56);
    *(x + 3) = (*(x + 2) << 8) | ((*(x + 2) & 0xff00000000000000) >> 56);

    return x;
}

uint64_t rand_xs64(uint64_t *x)
{ 
    uint64_t t = (*x ^ (*x << 11));
    *x = *(x + 1);
    *(x + 1) = *(x + 2);
    *(x + 2) = *(x + 3);
    *(x + 3) = (*(x + 3) ^ (*(x + 3) >> 19)) ^ (t ^ (t >> 8));
    return *(x + 3);
}

void close_xs64(uint64_t *x)
{
    if (x) {
        free(x);
        x = NULL;
    }
}
#include <stdio.h>
#include <inttypes.h>
#include "xorshift.h"

int main(void)
{
    uint64_t *seed = srand_xs64();
    if (!seed)
        return -1;

    for (int i = 0; i < 100000)
        printf("%"PRIu64"\n", rand_xs64(seed));

    close_xs64(seed);
    return 0;
}

とりあえず10万個程度の乱数を発生させてみてもダブりがひとつも出ないし(当たり前なんだろうけど)、スピードも速いみたい。
素晴らしい!

2012年4月7日土曜日

BucketMedian その2

更新。
パラメータを追加しました。

BucketMedian-0.2.0.zip
https://github.com/chikuzen/BucketMedian/

新パラメータ int "thresh"

ただのメディアンフィルタだと、radiusをちょっと高くしただけでも酷いことになるので、しきい値をもう一つ追加しました。
ソースのピクセル値と算出したメディアンの差がこの値以下の場合のみ、ピクセル値をメディアンに変更します。

これを5くらいにしておくと、なんかエッジをぼかさずにゴミがよく取れるようです。

2012年4月4日水曜日

BucketMedian

ここ一週間ほど基本的なアルゴリズムとかを勉強していたらなにか書きたくなったので、基本中の基本なメディアンフィルタを書いてみました。

BucketMedian-0.1.0.zip
https://github.com/chikuzen/BucketMedian/

メディアンを求めるのにバケツソートをちょっと応用してみましたが、あまり速くないですな。

使い方:
AVISource("herpderp.avi")
BucketMedian(clip c, int "radius", int "min", int "max")
clip:
 planar format(YV12,YV16,YV24,YV411,Y8)のみ対応。
 処理は輝度のみで、色差はまったくいじりません。

radius (1~255, デフォルト1): 参照する近傍ピクセルの半径。
 処理するピクセルを中心として、1だったら3x3、nだったら(2n+1)x(2n+1)の
近傍ピクセルのメディアンを求め、入れ替えます。
 大きくすればするほどボケて、遅くなります。

min (0~254, デフォルト0): しきい値の下限。
 これよりもピクセルの輝度が低い場合、そのピクセルはメディアンを求めず、そのままコピーします。

max (1から255, デフォルト255): しきい値の上限。
 これよりもピクセルの輝度が高い場合、そのピクセルはメディアンを求めず、そのままコピーします。

必要なもの:
 avisynth2.5.8以降
 Microsoft Visual C++ 2010 再頒布可能パッケージ