MalibFilterの重要なサブクラスのひとつにMalibMergerがある。 MalibFilterがひとつのバッファからの入力を前提としているのに対し、 MalibMergerでは複数のバッファからの入力に基づく処理を前提としてい るとの違いがある。
またMalibFilterクラスは抽象クラスであるため、それ自体のオブジェクトは生成され ないが、malib_filter_set_buffer()、 malib_filter_set_frame_info()などの リファレンスカウンタ操作を備えたバッファやサンプルフレーム情報オブジェクト を接続するための関数のように、いくつか重要な関数が用意されている。
これらの制限は、メンバ変数acceptableに記述する。その値としては、 frame.hで定義されるカラーモデル値を用いることができる。カラーモデルの 値は次に示すとおりビットフィールドに関して独立の値となっており、 論理和を取ることで複数の入力許容性を示すことができる。
#define MALIB_FRAME_COLORMODEL_RGB 0x0001 #define MALIB_FRAME_COLORMODEL_GREY 0x0002 #define MALIB_FRAME_COLORMODEL_BW 0x0004 #define MALIB_FRAME_COLORMODEL_RGB_A 0x0008 #define MALIB_FRAME_COLORMODEL_GREY_A 0x0010 #define MALIB_FRAME_COLORMODEL_BW_A 0x0020
フィルタクラスの各サブクラスを実装するにあたっては、 そのコンストラクタの記述を簡潔にするためのマクロ定義 MALIB_FILTER_GENERIC_NEW(klass, vtbl, accepts) などが用意されており、この時点でacceptableの値を設定することが できる。
例えばMalibMovingaveは、その入力形式として RGBカラーモデルまたはグレースケールモデルのデータを許容する。 このクラスのコンストラクタでは、下記のように論理和をとり その旨を指定することが可能となっている。
MalibMovingave*
malib_movingave_new ()
{
MALIB_FILTER_GENERIC_NEW ( MalibMovingave, &malib_movingave_class,
(MALIB_FRAME_COLORMODEL_RGB
| MALIB_FRAME_COLORMODEL_GREY) );
}
以下、例としてRGBカラーデータをグレースケールに変換するフィルタの実装に 基づいて説明する(rgb2grey.c)。
static MalibRgb2GreyClass malib_rgb2grey_class =
{
(void (*)(MalibObject*)) malib_filter_delete,
(void (*)(MalibSource*, MalibFrame*)) malib_rgb2grey_write_frame_data
};
MalibRgb2Grey*
malib_rgb2grey_new ()
{
MALIB_FILTER_GENERIC_NEW ( MalibRgb2Grey, &malib_rgb2grey_class,
MALIB_FRAME_COLORMODEL_RGB );
}
MalibRgb2Grey*
malib_rgb2grey_new_with_buf (MalibBuffer* buf)
{
MALIB_FILTER_GENERIC_NEW_WITH_BUF ( MalibRgb2Grey, malib_rgb2grey_new,
malib_rgb2grey_set_buffer, buf );
}
なおこの例では、グレースケールに変換するためサンプルフレーム情報を 入れ替える必要があり、そのためバッファをセットする関数として独自の 関数である malib_rgb2grey_set_buffer を指定している。 この関数では、次のようにカラーモデルを指定する形式のバッファ設定 関数を呼ぶ。
void
malib_rgb2grey_set_buffer (MalibRgb2Grey* filter, MalibBuffer* buf)
{
/* create new frame, which has almost all the same information
except data format (rgb -> grey), and timestamp */
malib_filter_set_buffer_with_colormodel ((MalibFilter*)filter, buf,
MALIB_FRAME_COLORMODEL_GREY);
}
static void
malib_rgb2grey_write_frame_data (MalibRgb2Grey* filter, MalibFrame* frame)
{
MalibBuffer* input;
unsigned int i, j;
unsigned int image_size;
/* the flag whether we need to propagate previous section */
int need_increment = 0;
/* pointers to rgb frame data and data area to store
the result of calculation */
int* rgb;
int* grey;
g_return_if_fail (filter && frame);
g_return_if_fail (((MalibFilter*)filter)->buf && frame->data);
input = ((MalibFilter*)filter)->buf;
grey = frame->data;
/* increment previous buffer data */
MALIB_OBJECT_COUNT_REFERENCES (filter, need_increment);
if (need_increment)
{
malib_holder_increment_frame ((MalibHolder*)input);
}
/* get pointers to rgb frame data */
rgb = malib_buffer_get_current_frame (input) ->data;
image_size = malib_filter_calc_output_image_size
((MalibFilter*) filter);
/* calculate greyscale value of rgb data */
for (i = 0, j = 0; i < image_size; i++, j += 3)
{
grey[i] = (int) (0.299f * (float) rgb[j]
+ 0.587f * (float) rgb[j+1]
+ 0.114f * (float) rgb[j+2]);
}
}
重要な点は、実際の画像生成処理を実施する前にリファレンスカウンタの チェックを行ない、必要であれば前段のバッファのフレームを更新することを 忘れないことである。上記のリスト中では、次の部分が該当する。
/* increment previous buffer data */
MALIB_OBJECT_COUNT_REFERENCES (filter, need_increment);
if (need_increment)
{
malib_holder_increment_frame ((MalibHolder*)input);
}
そこで構造体 MalibMergerBufInfo (バッファ情報構造体)を導入する。
typedef struct _MalibMergerBufInfo MalibMergerBufInfo;
/* optional buffer information */
struct _MalibMergerBufInfo
{
/* see filter.h */
MalibBuffer* buf;
unsigned int acceptable;
};
この構造体は入力バッファへのポインタと許容するデータ形式のフラグを組にした もので、MalibMergerはこの構造体の配列へのポインタを 持つ。こうすることにより3個以上の入力を同じ枠組みで取扱うことが可能になる。 また配列の最後にはNULL値を書込んでおくことで、配列の終了を判定する ものとしておく(図3.12)。
なおそれぞれのバッファの取扱い(接続、消去など)は、MalibFilterでの リンクの扱いに準じる。
前段バッファのフレーム更新処理は、全ての入力バッファについてフレーム更新の ための関数呼び出しを行なう。 例えば、MalibOverlapでの該当部分を抜粋すると以下のようになる。
/* increment previous buffer data */
MALIB_OBJECT_COUNT_REFERENCES (filter, need_increment);
if (need_increment)
{
malib_holder_increment_frame ((MalibHolder*)input[0]);
malib_holder_increment_frame ((MalibHolder*)input[1]);
}