2012年1月30日月曜日

avs2pipemod その12

更新しました。

avs2pipemod-0.2.1.7z
https://github.com/chikuzen/avs2pipemod

*新機能'x264raw','x264rawtc'を追加

最近はdither hackやらx264がRGB圧縮に対応したりやらのおかげで、y4m出力の代りにrawvideo出力を使う頻度が結構高くなりました。
YUV4MPEG2は仕様で「使えるフォーマットは8bitのplanarYUVのみ」と決められているので、これらのためには使えないのです。
で、仕方がないので
$ avs2pipemod -rawvideo=vflip input.avs | x264_x64 - --demuxer raw --input-csp bgr --input-res 1280x720 --output-csp rgb --fps ...
とかやるわけですが、長いコマンドがいい加減めんどうなので省力化することにしました。

使い方
$ avs2pipemod -x264raw 1280x720_30fps_rgb24.avs
てな感じのコマンドを実行すると
- --demuxer raw --input-csp bgr --input-depth 8 --input-res 1280x720 --fps 30/1 --output-csp rgb
と標準出力に出力されます。

dither packageやflash3kyuu_debandのinterleaved出力を使う場合は、引数でinput-depthを指定するとwidthを1/2にしたコマンドラインが出力されます。
$ avs2pipemod -x264raw=16 2560x719_ntsc-film_16bit_yv24.avs
- --demuxer raw --input-csp i444 --input-depth 16 --input-res 1280x719 --fps 24000/1001 --output-csp i444
'x264rawtc'は、--tcfile-inを使う場合のためのもので、"--fps fpsnum/fpsden"は出力されません。
$ avs2pipemod -x264rawtc 640x480_yv411.avs
- --demuxer lavf --input-fmt rawvideo --input-csp yuv411p --input-depth 8 --input-res 640x480 --output-csp i422
筆者のようにCLIにCygwinやMSYSのBash/shell scriptを使っている人なら
$ avs2pipemod -rawvideo input.avs | x264 $(avs2pipemod -x264raw=16 input.avs) --crf 22 --preset slower ...
てな感じで、コマンド置換を利用すれば結構ラクになると思います。

cmd.exeな人の場合は…あいにく筆者はdosコマンドやbatは数年前に憶えることを放棄したので、さっぱりわかりません。
まあ、某ペンギン様も「batを憶えるくらいならPerlをインストールしろ」とか言ってますし、それでいいかと思っています。

2012年1月28日土曜日

avs2pipemod その11

更新しました。
avs2pipemod-0.1.2.7z
https://github.com/chikuzen/avs2pipemod

エラーの出るavsを使用した際にクラッシュしていたのを修正。

生まれて初めてバグレポート頂きました。
これまでずっとレポートする側だったので、なんか新鮮な気分です。

2012年1月7日土曜日

ConvertToRGB

avcodecに10bit-AVCデコーダがcommitされて随分経つのにいまだによく解らない人のための乱暴な解説。

まずはこちらの方の解説を読みましょう。
自分が知るかぎりでは、もっともシンプルでわかりやすい説明をされています。
DTVかくし味 - YUVとRGBの比較

特にこの図、
いかに暗部の色数が少ないか、なぜ暗部にシルバーグレインを撒く(=Yの値だけまばら且つ適当に上げる)とマシに見えるようになるかが一発で理解できます。

さて、「YUVはRGBで表現できる範囲をすべてカバーしています。(が、細かい諧調はRGBに分があります。)」とまとめられていますが、これをちょっと具体的に計算してみましょうか。
/* yuv2rgb.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SATURATE(X) X = (X < 0) ? 0 : (X > 255) ? 255 : X

int main(void)
{
    const struct {
        char *name;
        int coef[6];
    } matrix[] = {
        {"rec601", {76309, 104597, 25675, 53279, 76308, 132201}},
        {"pc601",  {65536,  91881, 22553, 46801, 65536, 116129}},
        {"rec709", {76309, 117504, 13954, 34903, 76308, 138453}},
        {"pc709",  {65536, 103219, 12257, 30659, 65536, 121621}},
        {NULL}
    };

    int count = 256 * 256 * 256;
    int *rgb = (int*)calloc(count, sizeof(int));
    if (!rgb) {
        fprintf(stderr, "malloc failed\n");
        return -1;
    }
    for (int m = 0; matrix[m].name; m++) {
        int coef0 = matrix[m].coef[0], coef1 = matrix[m].coef[1],
            coef2 = matrix[m].coef[2], coef3 = matrix[m].coef[3],
            coef4 = matrix[m].coef[4], coef5 = matrix[m].coef[5];
        int x = !strncmp(matrix[m].name, "rec", 3) ? 16 : 0;

        for (int y = 0; y < 256; y++) {
            for (int u = 0; u < 256; u++) {
                for (int v = 0; v < 256; v++) {
                    /* 下記計算式は茂木和博氏のm2v.vfpのreadmeより引用しました */
                    int r = (coef0 * (y - x) + coef1 * (v - 128)) >> 16;
                    int g = (coef0 * (y - x) - coef2 * (u - 128) - coef3 * (v - 128)) >> 16;
                    int b = (coef4 * (y - x) + coef5 * (u - 128)) >> 16;
                    SATURATE(r);
                    SATURATE(g);
                    SATURATE(b);
                    rgb[((r << 16) | (g << 8) | b)]++;
                }
            }
        }

        int num = 0;
        for (int i = 0; i < count; i++) {
            num += !!rgb[i];
            rgb[i] = 0;
        }
        printf("%s: %d\n", matrix[m].name, num);
    }
    free(rgb);
    return 0;
}
このコードでBT.601とBT.709で8bitYUV->8bitRGBに変換した際、RGBで使われる色数がわかります。 で、結果は
BT.601 TVレンジ(伸張)      2,956,082色
BT.601 PCレンジ(ストレート) 4,261,687色
BT.709 TVレンジ(伸張)      3,048,157色
BT.709 PCレンジ(ストレート) 4,400,772色
となります。
いやぁ、ほんと色数少ないですね。TrueColorRGBの16,777,216色のうち、最大でも4分の1程度しか使われていません。
バンディングが発生するのも当たり前です。
これが10bitYUV->8bitRGBだとどの程度になるのかは、適当な計算式がとりあえず見当たらなかったのでやってませんが、8bit->10bitでY,U,Vの精度がそれぞれ4倍になることを考えれば、色数もかなり良い感じに増えそうです。

てなわけで、10bitエンコードの力を確認するためにバカ高い業務用モニタ等は別に必要ありません。
民生品でもそこそこの品質があれば違いは確実にわかります(もちろん、良いものであればもっとよく分かるでしょうが)。

つーか、AviUtlのプレビューがやたら綺麗に見える理由って、まさにこれだよね。

2012年1月5日木曜日

avs2pipemod その10

更新しました。

avs2pipemod-0.1.1.7z
https://github.com/chikuzen/avs2pipemod

コードの大部分を書き直しました。

* avisynth.libが要らなくなった。
これまではビルドするためにavisynth.libを使う必要がありましたが、これをやめてLoadLibrary()を使うようにしました。
これにより64bit用もビルド出来るようになりました。

* avisynth.dllのバージョンを検出し、挙動を切り替えるようにした。
てなわけでavs2pipe26modはなくなりました。

* おまけ
SetMTModeに応じてDistributor()を自動追加する機能もコードには存在します。
もし、この機能が欲しい人は、make時に'XCFLAGS=-DBLAME_THE_FLUFF'を追加して自ビルドして下さい。