FreeBSDでDVカメラを繋いでクレイアニメ

以前テレビチャンピオンのクレイアニメ選手権でやってたんですが、世の中にはランチボックスなるクレイアニメ専用の機械があるらしいです。値段いくらくらいするんですかねぇ・・・

と、そこまで買うのはバカバカしいような気もするので、持ち前のものでなんとかならんかと頑張ってみました。

以前はデジカメ>三脚でクレイアニメを作ろうとしてシャッター押すときのブレに閉口したわけですから、シャッターを手で押さないというのがポイントではないかと思います。

ということはPCから制御すれば万事解決。これなら被写体をそこに置いたら、あとはiLink経由で画面をキャプっていけばいいことになります。

また、DVは編集するソフトも充実しているので、撮ったあとも簡単そうです。そこで、今回は普通のDVカメラでPC制御でなんとかならんかと挑戦をしてみました。

対象OSは愛機FreeBSD。

いきなりWindowsでもLinuxでもMacOSXでもないわけですが、いろいろ検討した結果、これが一番カスタマイズが簡単で、ワタシの要求に答えるということになりました。

FreeBSDは fwcontrolなるFirewireを制御するコマンドがOS標準で入っているので、画像を撮るだけであれば、カメラをPCにiLinkケーブルで繋げば、準備は終了です。その後おもむろに、

# fwcontrol -R filename


を実行すると延々とカメラの画像をファイルに書き込んで行きます。ホントウに書き込まれたかどうかはplaydvなるソフトを/usr/ports/multimedia/libdvから入れて確認すればよいでしょう。
止めるのはControl-Cを押したときです。

しかし、このコマンド便利は便利なんですが、止めるのがControl-Cというのがメンドクサイ。なんとかならんものかということで、fwcontrolのソースを眺めました。(/usr/src/usr.sbin/fwcontrol)

すると、このコマンド。コード的には、二つのファイルしかなく、行数も1000行チョイ。余計な機能をはぶいて本質的なところだけをコンパクトに書く。こういうコードは分かりやすく、また、改造するのも用意なのです。これがワタシがBSDを推す理由の一つでもあります。

さらに眺めているとカメラのデータを取得する関数

dvrecv(int d, char *filename, char ich, int count)


というのがあり、ここのcountに欲しいフレーム数を渡してやれば、そのフレームだけ撮影して終了するようです。(オリジナルは-1固定になっている)

というわけで、あっさりパッチが出来ました。ここに(例えば30のような)固定値を入れてもいいんですが、コマンドラインのオプションで変更できたほうがいいだろうということで、-nオプションでキャプるフレーム数を指定するようにしました。

キャプったdvファイルはシーン別に番号をつけて管理し、dv修正ソフトで切ったり、繋いだり、タイムシーケンスの調整をします。

これにはkinoというフリーソフトを利用しました。kinoはWindows Movie Makerライクな編集ができるソフトでフリーソフトのわりには必要な機能がほとんどつまっていて便利です。kinoは /usr/ports/multimedia/kinoに入っています。

というわけで、そのあたりを駆使して作られたアニメがdigdug2.jpeg

まだ断片的にしか出来てませんが・・・デジカメより圧倒的にブレが少なくなった。

と、言ったわけで、もう作るためのシステムは確立したんで、あとは作るだけ・・・なんですが、これがまたオッソロしく大変なことが分かってきました。

今回も板や撮影順序を間違え、リテイクのアラシ。これより複雑なアニメとなると・・・想像もしたくないですな・・・・

--- fwcontrol.c-        Wed Jul 13 16:17:18 2005
+++ fwcontrol.c Wed Jul 13 16:19:02 2005
@@ -61,7 +61,7 @@
        fprintf(stderr,
                "fwcontrol [-u bus_num] [-rt] [-g gap_count] [-o node] "
                    "[-b pri_req] [-c node] [-d node] [-l file] "
-                   "[-R file] [-S file]\n"
+                   "[-R file] [-S file] [-n count]\n"
                "\t-u: specify bus number\n"
                "\t-g: broadcast gap_count by phy_config packet\n"
                "\t-o: send link-on packet to the node\n"
@@ -73,7 +73,8 @@
                "\t-d: hex dump of configuration ROM\n"
                "\t-l: load and parse hex dump file of configuration ROM\n"
                "\t-R: Receive DV stream\n"
-               "\t-S: Send DV stream\n");
+               "\t-S: Send DV stream\n"
+               "\t-n: Recevie DV stream count\n");
        exit(0);
 }
 
@@ -601,6 +602,7 @@
        u_int32_t crom_buf[1024/4];
        char devbase[1024] = "/dev/fw0";
        int fd, i, tmp, ch, len=1024;
+       int count = -1;
 
        fd = -1;
 
@@ -609,7 +611,7 @@
                list_dev(fd);
        }
 
-       while ((ch = getopt(argc, argv, "g:o:s:b:prtc:d:l:u:R:S:")) != -1)
+       while ((ch = getopt(argc, argv, "g:o:s:b:prtc:d:l:u:R:S:n:")) != -1)
                switch(ch) {
                case 'b':
                        tmp = strtol(optarg, NULL, 0);
@@ -676,11 +678,14 @@
 #define CHANNEL        63
                case 'R':
                        open_dev(&fd, devbase);
-                       dvrecv(fd, optarg, TAG | CHANNEL, -1);
+                       dvrecv(fd, optarg, TAG | CHANNEL, count);
                        break;
                case 'S':
                        open_dev(&fd, devbase);
                        dvsend(fd, optarg, TAG | CHANNEL, -1);
+                       break;
+               case 'n':
+                       count = strtol(optarg, NULL, 0);
                        break;
                default:
                        usage();

Posted by issei

カテゴリ: 雑記