【C/C++】 streamクラスのeofメンバ

以下の記事でstreamクラスのeofの扱いが難しいという記事を書いたんやけど、まぁこれやったらと許容できる方法を考えたので載せておこう。

【C/C++】ifstreamのeofメンバ関数(違和感のある挙動)

ちなみに以前はifstreamについて書いたんやけど、調べてみるとstream系のeofは全て同じ実装みたい。
つまり、実際に最終要素にアクセスした後でないと、正確なeofを検出できないと。

そこで、以下のようにすると、うまく動きます。
ん〜、読み出し部分が2行あって気持ち悪いけど、一応これやったらちゃんと対応できてると思うんよね。

istringstream s(buff);
string line;

s >> line;                <-- ミソ
while( !s.eof() ) {
    〜何らかの処理〜
    s >> line;
}

単純にwhileループをeofメンバで終了判定するのやけど、その時にwhile文の直前に一回読み出しを行ってしまおうと。

要素数が0の場合:  while文に入らず終了(処理されない)
要素数が1の場合:  while文に入り処理が1回実行。次のループ条件が偽になりループから抜ける。
要素数が2の場合:  上記の繰り返し

という事で、うまく行きそうですな。
ん〜、なるほど。こういう思想で設計されているんやね。

| | コメント (0) | トラックバック (0)

【Linux Tips】 テキストファイルの一括置き換え/ファイル名の一括置き換え

久しぶりの覚書き。

perlを使った1ラインコマンドでのテキストファイルの一括置き換え方法

$ perl -p -w -i.bak -e "s/置換前文字列/置換後文字列/g" ファイル名

さらにfindを組み合わせ複数ファイルを一括処理する方法

以下のどちらでもOK。実は他にも色々と方法はある。

$ find . -name ファイル名パターン | xargs perl -p -w -i.bak -e "s/置換前文字列/置換後文字列/g"
$ find . -name ファイル名パターン -exec perl -p -w -i.bak -e "s/置換前文字列/置換後文字列/g" {} \;

もちろんperlの強力な正規表現が使えます。

ファイル名の一括置き換え方法

大量のファイルの拡張子を一気に変更とか、色々できまする。
通常は rename コマンドを使えば良いのだけど、CygwinとかMinGWではrenameが無いっぽい。
よって、シェルスクリプトと組み合わせて以下のようにすると良い。

$ find . -name ファイル名パターン | while read file; do mv $line `echo $file | sed -e 's/置換前文字列/置換後文字列/'`; done

う〜む、Linuxコマンドラインの世界は奥が深いですなぁ。think


» 続きを読む

| | コメント (0) | トラックバック (0)

ココログの設定について

今までやってみたかったのだけど、やりかたが分からなかった事。
↓みたいに、本文を別リンクにする事...。coldsweats01

» 続きを読む

| | コメント (0) | トラックバック (0)

【SystemC】 SystemC with MinGW, MSYS

システムシミュレーションをするべくSystemCを勉強中やねんけど、C++が使える人にとっては、これは楽やなぁ。
HDLを使ってるデジタルハード屋さんにはちょっと厳しいかもしれへんけどね。

ってな事で、基本的にソフト屋さんな僕としてはSystemCは特に違和感なく取っ掛かる事ができました。
まださわりだけやから、これから色々と調べなくちゃならん事があるかもしれへんけど...。

SystemCの動作環境についてです。
メインマシンはubuntuなので、殆ど問題なし。SystemCのサイトからパッケージをダウンロードしたら、普通に動きました。波形データもVCDファイルに落として、GTKwaveを使って見る事ができたしね。

Screenshotgtkwave_halfaddrvcd_2 ←半加算器を実装して波形観測した様子。





さて問題はWindows環境や。
Windows環境では僕は通常MinGW+MSYSを使ってるんやけど、SystemCのパッケージはcygwinを推奨しているみたい。
configureがMinGWには対応してないんですわ。そこで、ちょこちょこ〜っと変更してMinGW版のlibsystemc.aを作成してみました。以下、そのやり方を覚え書き。

MinGWで動作させるSystemC

  1. パッケージをダウンロードする
  2. ソースコードをコピー
  3. ソースを一部変更
  4. MinGW用のmakefileを作成してビルド
  5. オブジェクトファイルを抽出(バージョン2.2.0で78ファイル)
  6. アーカイバでライブラリ作成

こんな感じ。

1. は http://www.systemc.org/ にアクセスして、利用者登録してパッケージをダウンロードすればOK。
今現在の最新版は 2.2.0 ですわ。

2. 上でダウンロードしたパッケージを解凍すると

tar -zxvf systemc-2.2.0.tar.gz

config, docs, examples, src ...といったディレクトリができまする。
この内、srcのみを使いまする。
srcディレクトリを適当な場所にそっくりコピー。
元ファイルを取っておかなくてもよければ、このコピーは不要ですわ。

3. ソースを一部変更しまする。
SystemCのkernelやdatatypeといったコードはcygwinのg++に対応させているらしく、一部MinGWのg++ではエラーになる記述が存在するねん。あと、僕がgcc4を使っているからって事もあるのやけど、型不一致のエラーも出てたみたい。
という事で、以下のように修正します。

sysc/datatypes/int/sc_nbdefs.cpp
sysc/datatypes/int/sc_int64_mask.cpp

ファイルの先頭に以下の行を追加

#undef WIN32

これは、WIN32定義があると i64 記述子を使うようになっているためです。
MinGWのgccではi64記述子は使われへんようやね。コマンドオプションで何かあったような気がするんやけど、とりあえず手っ取り早くコードを変更しちゃいました。ご丁寧にもWIN32以外やったら、ULL記述子を使うようにコードが書かれてるし。

sysc/datatypes/int/sc_nbcommon.inc
2985行目で型不一致エラーになるので、std::_Ios_Fmtflagsへのキャストを追加。

os.setf((std::_Ios_Fmtflags)old_flags, ::std::ios::basefield);


sysc/kernel/sc_cor_fiber.h

PVOIDとかが未定義やってエラーになるんで、ファイル先頭に以下の行を追加。

#include <windows.h>

sysc/utils/sc_utils_ids.cpp
getenv関数とstrcmpの定義が見つからんってエラーになる。よってファイル先頭に以下の行を追加。

#include <stdlib.h>
#include <string.h>

110行目辺り、getenv関数を呼び出している所が、std::getenvを呼び出している。
stdlib.hのgetenvを使うので、stdスコープは余計ですな。削除しまする。

const char* deprecation_warn = getenv("SC_DEPRECATION_WARNINGS");

さぁ、これでコード修正が完了。

4. MinGW用のMakefileを作ってビルド。
まぁ、これは各自サクっとやっちゃってください。
僕の場合は普段から使っているmake ruleがあるんで、それで一期にやっちゃいました。
必要なんは、オブジェクトファイルを作る事なんで、リンクは不要っす。(というかできひん)
コンパイルだけやっちゃってくださいな。
findコマンドとg++でも一応できるけどね。
ちなみにコンパイル対象のディレクトリは

  • communications
  • datatypes
  • kernel
  • tracing
  • utils

だけでOKです。cygwinの環境では qt まで含めてるんやけど、とりあえず使わんでしょう。

5. コンパイルしてできた .oファイルをどこかのフォルダにコピーしてまとめて...

6. アーカイバでライブラリを作成しまする。

$ ar cq libsystemc.a *.o

こんな感じかな。
これで、MinGW環境で使えるlibsystemc.aがでけました。
あとは普通にSystemCのコード書いて、このライブラリをリンクしちゃってくださいな。

ふぅ、cygwinってシェルのパス変更するから好きやないんよなぁ。
という事で、何がなんでもMinGW+MSYSでという方向けの情報ですな。

| | コメント (0) | トラックバック (0)

【ubuntu】 CUPS with Canon iP4100の設定

ubuntu 8.04 LTS サーバでの Canon iP4100 プリンタの設定メモです。
こちらのサイトを参考にしました。

https://help.ubuntu.com/community/HardwareSupportComponentsPrinters/CanonPrinters/CanonPixmaIP4200#preview

手順は以下の通り。

  1. cupsysのインストール
  2. cups.confの編集
  3. alienのインストール
  4. CanonのサイトからiP4100のLinux版ドライバをダウンロード
  5. rpmパッケージをdebパッケージに変換
  6. ドライバのインストール
  7. プリンタの登録

迷うことはさほど無いんやけど、CUPSの立ち上げとドライバのインストールをそれぞれ行う必要がある事。
あと、Canonのサイトではrpm形式のパッケージしか提供されていないので、ubuntuではdebパッケージに変換する必要がある事くらいかな?

| | コメント (0) | トラックバック (0)

【C/C++】 マクロと関数呼び出し

仕事でちょっとはまったC言語の問題。
マルチプラットフォームでビルドしてたんやけど、謎なエラーが表示されててん。

コンパイルしたコードは以下の通り。

if ( condition ) test_func( ... );
else              test_func( ... );

エラー表示されたメッセージは

error: expected primary-expression before ‘else’

ってな感じでしたわ。
なんで else がパースされへんのか?と思って色々調査。

if ( condition ) test_func( ... )
else              test_func( ... );

とすると、コンパイルできました。
これはおかしい。
結局、よく調べてみると test_func というのは関数やなくて、マクロ関数で定義されていました。

#define test_func( ... ) { hogehoge(); fugafuga; ... }

こんな感じ。そのためプリプロで展開すると

if ( condition ) { hogehoge(); fugafuga(); ... };
else              { hogehoge(); fugafuga(); ... };

といった具合になって、1行目の末尾のセミコロンが悪さをしていました。
今回の問題は実はもうちょっと複雑で、片方のプラットフォームでは test_func は外部関数、もう片方のプラットフォームではマクロ関数で定義されていました。そのため、同じソースコードなのにプラットフォーム毎にエラーが起きたり起きなかったりと不可解な挙動をしたわけです。で、問題は回避方法。片方がマクロ関数である限り、セミコロンをつける事はできひんけど、外部関数の呼び出しでエラーになっていまう。逆もしかり。一番手軽な修正方法は中括弧をつける事かね。

if ( condition ) { test_func( ... ); }
else              { test_func( ... ); }

こんな感じにすればマクロ関数でも外部関数でも動作する。
せやけど、シングルステートメントの if〜else 文が書かれへんよなぁ。

色々悩んでいたんやけど、ふと昔見たことがあるテクニックを思い出しました。

#define test_func( ... ) do { hogehoge(); fugafuga(); } while(0)

って定義すれば良いんやった。wink
最後にセミコロンはつけへんように注意。
このマクロ関数はステートメントの末尾にセミコロンを持つ普通の関数のように扱えるわけや。
while(0)は結局ループなしになるので、コンパイラの最適化でループ自体が削除されて無駄な命令が出力される事もない。(はず。コンパイラの最適化機能によるかね。)

という訳で、無事に解決しました。

| | コメント (0) | トラックバック (0)

【ubuntu】 mediatomb での asf ファイル再生 with PS3

前回の記事(mediatomb on ubuntu 8.04)で、mediatombのconfig.xmlの変更について書いたんやけど、ファイルの種類が追加されてませんでした。あと、PS3でasfファイル(コーデックはVC-1)を再生しようとすると「破損データ」って表示されちゃう問題がありました。という事で、修正したconfig.xmlを。
修正すべき箇所は、/etc/mediatomb/config.xmlの真ん中あたり。
jpgやらpngやらmpgやらを追加しました。
それから、asfのmimetypeをx-ms-wmvにしました。
asfはコンテナタイプなので、実際には他のコーデックを含める事もできるのやけど、x-ms-asfってmimeをPS3が認識してくれていないので、まぁ致し方なくx-ms-wmvにしたと。とりあえず手持ちのasfファイルは殆どwmvだったので、こういう対応にしたけど、ファイルの拡張子を変更した方が楽かもしれへんなぁ...

      <extension-mimetype ignore-unknown="no">
        <map from="jpg" to="image/jpeg"/>
        <map from="jpeg" to="image/jpeg"/>
        <map from="gif" to="image/gif"/>
        <map from="png" to="image/png"/>
        <map from="m4v" to="video/mp4"/>
        <map from="mp4" to="video/mp4"/>
        <map from="mpg" to="video/mpeg"/>
        <map from="mpeg" to="video/mpeg"/>
        <map from="mp3" to="audio/mpeg"/>
        <map from="ogg" to="application/ogg"/>
        <map from="asf" to="video/x-ms-wmv"/>
        <map from="asx" to="video/x-ms-asf"/>
        <map from="wma" to="audio/x-ms-wma"/>
        <map from="wax" to="audio/x-ms-wax"/>
        <map from="wmv" to="video/x-ms-wmv"/>
        <map from="wvx" to="video/x-ms-wvx"/>
        <map from="wm" to="video/x-ms-wm"/>
        <map from="wmx" to="video/x-ms-wmx"/>
        <map from="m3u" to="audio/x-mpegurl"/>
        <map from="pls" to="audio/x-scpls"/>
        <map from="flv" to="video/x-flv"/>
        <!-- Uncomment the line below for PS3 divx support -->
        <map from="avi" to="video/divx"/>
        <!-- Uncomment the line below for D-Link DSM / ZyXEL DMA-1000 -->
        <!-- <map from="avi" to="video/avi"/> -->
      </extension-mimetype>

| | コメント (0) | トラックバック (0)

【ubuntu】 mediatomb on ubuntu 8.04

別にubuntuだけの話ではないのやけど、我が家のubuntuサーバでmediatombを動かすようにしたのでその設定を覚書き。
以前はCentOSでmediatombを動かして、PS3から音楽やらフォトやらビデオやらを見てました。で、今回はサーバがubuntu 8.04に変わったんで、再設定を。意外と色々はまるもんですなぁ。

以下手順を。

  1. mediatombのインストール
  2. config.xmlの設定
  3. mysqlの設定
  4. コンテンツ登録
  5. MP3 IDタグの文字コード変換

1. のインストールはもうええよね。パッケージマネージャをつかって、mediatombを一式インストールしてくださいな。この時にmysqlもインストールすると後々よろしいです。元々mediatombはsqlite3をバックエンドのDBとして使っているのやけど、sqlite3は遅い。mysqlの方が格段に早いっす。だからmysqlのご使用を強くお勧めしますだ。特に我が家の用にCDが700枚とかって枚数あって、リッピングしたら7000曲にもなった場合はその差が大きいっす。sad

2. config.xmlの変更やけど、ubuntuのパッケージマネージャでインストールすると、/etc/mediatomb/config.xmlにディフォルトのファイルが作られるはず。このファイルをちょこちょこ〜っと修正します。具体的にはファイル内でPS3用と書かれている箇所を有効にします。

<protocolInfo extend="yes"/>
<map from="avi" to "video/divx"/>

後者はDivXを再生しないのであれば、あんまり関係ないな。
その他の箇所は

    <storage>
      <sqlite3 enabled="no">
        <database-file>sqlite3.db</database-file>
      </sqlite3>
      <mysql enabled="yes">
        <database-file>mediatomb.db</database-file>
        <host>localhost</host>
        <username>mediatomb</username>
        <password>********</password>
        <database>mediatomb</database>
        <port>3306</port>
      </mysql>
    </storage>

この部分。sqlite3をnoにして、mysqlをyesに変更。
usernameとpassword、database、portを必要に応じて設定する。

  <import hidden-files="no">
    <filesystem-charset>UTF-8</filesystem-charset>
    <metadata-charset>CP932</metadata-charset>
    <scripting script-charset="UTF-8">
      <common-script>/usr/share/mediatomb/js/common.js</common-script>
      <playlist-script>/usr/share/mediatomb/js/playlists.js</playlist-script>

さらに日本語が使えるように、filesystem-charsetとmetadata-charsetを設定。
script-charsetはUTF-8にしておかないと正常に動作しないので要注意ですな。
charsetは色々試したけど、結局UTF-8にしておいて後述のEasyTAGで文字コード変換した方がちゃんと日本語表示されるみたいですわ。

3. mysqlの設定。
ubuntuのパッケージマネージャは何やらmysqlの設定もしてくれるんですかねぇ?何かDBができたような気がするのやけど、ここで色々はまったんで、もう手動でやっちゃいました。まずはmysqlをrootで立ち上げて...

$ mysql -u root -p

パスワード聞かれたら、とりあえず空パスを試してみる。パスワード変更してなければ空のはず。
とりあえず、DB一覧を見てみますか。

$ show databases;

最後のセミコロンを忘れずに。
既にmediatombという名前のDBがあったら、それを先に削除しまする。存在しなければこの作業はスキップ。

$ drop database mediatomb;

で、mediatombデータベースを新規に作成して、mediatombユーザにアクセス権限を付与する。

$ create database mediatomb;
$ grant all on mediatomb.* to 'mediatomb'@'localhost';
$ flush privileges;
$ quit

これで一旦mysqlから抜け出ます。
次にmediatomb DBに初期のテーブルを作成しますだ。これはmediatombのパッケージにsqlファイルが含まれているのでそれを使います。ただし、ちょっとだけ修正が必要かもしれない。(僕の場合は必要だった)

$ mysql -u root -p < /usr/share/mediatomb/mysql.sql

これを実行した時に「使用するDBが選択されていない」みたいなエラーが発生する場合は、mysql.sqlファイルをroot権限で開いて、先頭に use mediatomb; という行を追加してくださいな。
無事mysql.sqlでのテーブル作成ができたら完了。

5. コンテンツ登録。
ブラウザで http://サーバ名:49152/にアクセスする。
mediatombの管理画面が表示されるので、「filesystem」を選択した登録したいディレクトリもしくはファイルを選択して右上の+ボタンを押す。○付きの+ボタンを使うと一定時間毎に指定したディレクトリ以下のメディアファイルをスキャンして登録するといった事もできるので便利。

登録が完了すれば、PS3から無事再生できるかを確認する。
うまく動かない場合は、/var/log/mediatomb.log を見て何が起きているかを調べる。
まぁ、大抵はmysqlサーバに接続できなかったとかって表示されると思うんやけど。

6. タグの文字コード変換。
これはちょっとおまけ。上記までで無事再生はできると思うのやけど、メタ情報が文字化けする問題が多発した。
原因は文字コードで、僕の使っていたリッピングツールだとMP3のIDタグがShift_JISでエンコードされてたみたい。でもmediatombではUTF-8を指定していたので文字化けして見れなくなってた。この際なんで、ファイルシステムと同じくUTF-8に変換しようと思った所、EasyTAGというツールを発見しました。
さっそくパッケージマネージャを使って、EasyTAGをインストール。設定画面で、読み込み時の文字コードをShift_JISにして書き込み時の文字コードをUTF-8に設定。この状態でファイルをスキャンして全部書き換えるようにしました。かなり時間かかったけど手間はかからんかったね。これで無事PS3のDLNAクライアント上でも日本語タイトルが表示されるようになりましたっと。

ふぅ、今日は長かったな。coldsweats02

| | コメント (0) | トラックバック (0)

【PS3】 ubuntu 8.10/9.04 on PLAYSTATION3

ubuntu 9.04をPLAYSTATIN3にインストールしてみた。
最初、ubuntu 8.10をインストールしたのやけど、アップデートマネージャで9.04に上げました。メモリ不足もあって、ちょっともたつくけど、とりあえず特に問題なし。CentOSやFedoraなんかよりも起動が早くて良い感じ。これで、SPUのプログラミングもubuntuでできるね。実際には、メインPCでクロス開発する事になると思うけど...。

ちなみに、ubuntu on PLAYSTATION3のインストール方法は以下の通り。
僕は8.10から入れたけど、今は9.04のイメージもあるので、それを使っても同じかと思いまする。メインマシンにはなり得ないけど、とりあえずCellの開発サーバにするつもりやったので、サーバエディションで良いかもしれない。(とは言え、一応デスクトップエディション入れましたダhappy02

  1. パッケージのダウンロード
  2. CDに焼いて...
  3. インストール

で、終わり。
いや、ホンマの話、めっちゃ楽なんすわ。ただし、ちょっとハマりポイントがあるので以下に覚書しときまする。Bluetooth機器とかPS3のコントローラーとか使うためにはもうちょっと手間がかかるみたいやけど、インストールできて、ネットワークつながりゃ良いねんって場合には上記でOK。

パッケージは以下にあります。

ubuntu 8.10
http://cdimage.ubuntu.com/ports/releases/8.10/release/

ubuntu 9.04
http://cdimage.ubuntu.com/ports/releases/9.04/release/

まず、Server Installとするか、Alternate Installするかを決めて、必要なパッケージをダウンロードする。PS3で何か操作するんやなかったら、Server Installで良い気がする。個人的には、PS3はデスクトップではなくてSSH経由で操作するリモート開発マシン(orトランスコーダ)なのでデスクトップは必要なかってんけど、まぁ勢いでAlternate Installを使いました。

次、CDに焼く。
ubuntuならめっちゃ楽。
空のCD(650MB以上必要)をドライブにセットして、上でダウンロードした .iso ファイルを右クリック、CDに書き込む。
しばらくするとホカホカのインストールCDができまする。(我が家のPCでCDを焼くと文字通りホカホカになる...coldsweats02 回転速度のせいか、環境のせいか熱を持つのだよ。)

PS3でその他のOSのパーティションを作っておく。この辺は色々と解説あるんで、そっちをgoogle先生に教えてもらってくださいな。わたしゃ実はPS3の開○者なんで、その辺はちょっとすっ飛ばします....bleah ちなみに内部データのバックアップをしっかり取っておかないと、後悔しますぜ。というか、バックアップ対象にならないデータもあるから、ホンマは購入直後のPS3で別OS用のパーティションを確保しておいた方が良いね。

ホカホカのCDをPS3にセットして、「本体設定」から「その他のシステムのインストール」を選択。これで、ブートローダーが書き換わる。ちなみに、ここがハマりポイントで、ブートローダーとKernelのバージョンに依存性があるので注意が必要。途中でブート仕様が変わってるんでね。古いブートローダを使って、ubuntu 9.04みたいな新しいkernelを起動しようとすると kboot: でenterを押しても何度も kboot: が表示される(つまり起動しない)問題が発生する。この場合も、一旦XMBに戻ってubuntuのインストールディスクをセットし、「本体設定」から「その他のシステムのインストール」を行えば大丈夫。

さてさて、無事インストーラが起動したら後はメッセージにしたがって入力すれば良し。途中でSATAのRAIDコントローラー使うか?みたいなの聞いてくるけど、そもそもRAIDにする意味ないんで無しの方が良いと思うです。あとキーボードの自動設定は時間がかかる割にハズレが多いみたいやから、手動で設定した方が確実やね。

そんなこんなで、PS3上のubuntu 9.04ですが、一応1分程度で起動するLinuxとなりました。
でも、アプリの起動はめっちゃ重いですなぁ。理由は色々あるのやけど...

理由その1

メインメモリが256MBしかない。
しかもHypervisorに一部をリザーブされる。
PS3にはグラフィック用のメモリ256MBもあるのやけど、これはLinuxでは使用する事ができない。

理由その2

グラフィックのアクセラレーションが利用できない。
その1のグラフィックメモリが使えない件とも被るのやけど、PS3ではLinux向けにグラフィックチップのドライバを公開していない。

理由その3

全てのデバイス操作はHypervisorコールを経由する。
PS3ではHypervisorの上にLinux Kernelが載っているため、基本的に全てのデバイス操作はHypervisorコールを利用しなければならない。つまりシステムコールの先にHypervisorコールがいるため、その分オーバーヘッドが大きい。特にストレージ関係は遅いんちゃうかな?

理由その4

CellのPPUはインオーダーのスーパースカラ型なので、通常のPCのようなアウトオブオーダー型の投機実行ができない。よってパイプラインのストール頻度が高くなる傾向にある。

理由その他

他にも色々あるけど、さすがにここには書けないなぁ。細かい話ではあるけど。とりあえずCell BEのドキュメントを読むと、PS3のプロセッサがなぜそれほど早くないのか良く分かると思う。普通のCore2とかと比べてはイカンのだよ。どちらかというとAtomと比べるべきかな。

ただ〜し、SPUを使うと話は変わってくる。SPUは強力なSIMD型ストリームプロセッサで、これを利用する事で見かけの性能を大幅にアップする事ができる。つまりPS3は汎用コンピュータではなく、やはりあくまで組み込み機器なんですなぁ。かなりプログラマブルではあるけど。

PS3での開発の詳細は、また今度にしよう。

| | コメント (0) | トラックバック (0)

【OpenCV】 cvWaitKeyのタイムアウト時間とフレーム更新

ubuntuでOpenCVのプログラムを作る時、ビデオやカメラとかの入力から1フレーム取得して表示してという処理を繰り返すのやけど、その時のcvWaitKeyのタイムアウト時間を1msに設定すると画面更新が行われないっぽい。2ms以上だと(マシンスペックにもよると思うけど)ちゃんと表示された。
どんな感じかと言うと...

int main( void )
{
    CvCapture* capture = cvCreateFileCapture( ファイル名 );
    cvNamedWindow( "VIDEO", CV_WINDOW_AUTOSIZE );
    while( 1 ) {
        IplImage* frame = cvQueryFrame( capture );
        cvShowImage( "VIDEO", frame );
        int key = cvWaitKey( TIMEOUT ) & 0xFF;
        if ( key == 0x1B ) break;
    }
    cvDestroyAllWindows();
    cvReleaseCapture( &capture );
}

ってなコードで、ファイル名で指定した動画ファイルの各フレームを取得しながら、VIDEOというタイトルのwindowに表示できるのやけど、この時、cvWaitKeyのTIMEOUTを2ms以上にしないと描画されない(Windowに何も表示されない)現象が起きる。おそらく描画ルーチンが動くよりもこのタイムアウトが先に発生してメインスレッドがスケジューリングされてしまっているのだと思われる。

ま、一般的に動画であれば30fps辺りやから、ほぼリアルタイムで表示がしたければ TIMEOUT を 33 にしておくと概ね実際の動画と同じように表示されるはず。画像処理とかで一気に結果を確認したい時は2ms〜10ms位にしておけば、マシンパワーにもよるけど一応そのマシンの最高速で処理されるでしょう。

とまぁ、ちょっとだけハマった話から覚え書き。

| | コメント (0) | トラックバック (0)

«【VirtualBox】共有フォルダ