2011年12月21日水曜日

is_writable の実装探しの旅

pgpoolAdmin のインストール時のエラーの続き。

selinux が原因だったので、 is_writable の実装探しの旅に出ても結局分からなかったと思われる。
が、気になったので、実装探しの旅に出てみることにした。

emacs + cscope で読むことにする。
php のソースコードを展開して、cscope のファイルを作成。
$ cd php-5.3.8
$ find ./ -name "*.h" -or -name "*.c" > cscope.files
$ cscope -b -q -k
emacs で展開したディレクトリあたりを開いて、 M-x cscope-find-global-definition is_writable を実行。
まぁそう簡単には見つからない。M-x cscope-find-this-symbol is_writable でいくつか候補が。
その中でそれっぽいのが、
*** ext/standard/php_filestat.h:
<global>[39]                   PHP_FUNCTION(is_writable);
...
*** ext/standard/basic_functions.c:
ZEND_END_ARG_INFO[3194]        PHP_FE(is_writable, arginfo_is_writable)
宣言と定義っぽいのが見つかったが、マクロのようだ・・・

宣言っぽいほうを追っていくと
#define ZEND_FN(name) zif_##name
とか出てくる。zif_iswritable とか作られているのだろうか。

次に定義っぽい方を追っていくと、
const zend_function_entry basic_functions[] = { /* {{{ */
  [snip]
    PHP_FE(is_writable,       arginfo_is_writable)
となっている。
関数ポインタを持った構造体の配列?これを追うのは大変そうだ・・・そもそもの仕組み知らないし・・・呼び出し元が探せない・・・
という訳で、GDB でステップ実行してみることに。

http://d.hatena.ne.jp/anatoo/20111117/1321463886
を参考にまず、まずコンパイル。
$ ./configure --disable-all --enable-debug
$ make
でテスト用のスクリプト(~/test_is_writable.php)を作成。(前回通らないと思ってたが Web 経由だとユーザが異なっていてパーミッションの問題だったかも・・・パーミッション確認後、再度実行したらこのスクリプトは true となった)
<?php
echo is_writable('/usr/local/etc/pgpool.conf');
次に、GDB で実行。
$ gdb sapi/cli/php
(gdb) break zif_is_writable
Breakpoint 1 at 0x509b30: file /usr/local/src/php-5.3.8/ext/standard/filestat.c, line 1092.
(gdb) run ~/test_is_writable.php
後は、s と n で辿っていく。
ext/standard/filestat.c:782 の php_stat が実装のようだ。
さらに入っていくと、
eck_open_basedir_ex (path=0xb03350 "/usr/local/etc/pgpool.conf", warn=1)
    at /usr/local/src/php-5.3.8/main/fopen_wrappers.c:297

 if (PG(open_basedir) && *PG(open_basedir)) {
あたりだろうか。
PG の定義は、
# define PG(v) (core_globals.v)
extern ZEND_API struct _php_core_globals core_globals;
_php_core_globals の open_basedir が設定されているかどうかを見ているっぽい。
が、open_basedir が分からない。
ググッて見ると、php.ini にそういう項目があるようだ。
このあたりをいじればいけるかと思ったがそうでもなかった。

テストスクリプトだと true となるのでこのあたりで断念。
結局追えなかった・・・

2011年12月12日月曜日

pgpoolAdmin のインストール時のエラー

今回は、pgpoolAdmin を検証するためにインストールしていた時に嵌まったことを。

pgpoolAdmin を展開後、http://www.example.com/pgpoolAdmin/install/index.html にアクセスしてインストール作業を続けるわけだが、/usr/local/etc 以下の pgpool.conf や pcp.conf が "Write access denied" となっていて先に進めない。

ファイルのパーミッションや所有者を確認してみるが特に問題はなさそうだ。
PHP で作られているようなので中身を見てみることにした。

install/checkParameter.php 60
if (!is_writable($pgpool2_config_file)) {
  $msgPgpoolConfigFile = 'Write access denied';
  $error = TRUE;
}
となっている。

実行ユーザを調べるために
echo `id`;
を埋め込んでみるも、想定通りのユーザで動いてそうだ。

スクリプトからパーミッションを取得するために
var_dump(stat($pgpool2_config_file));
を埋め込んでみるも、
["mode"]=> int(33188)
となっており、8 進数で 100644 となり、これも問題なさそう。

is_writable のみを記述したテストプログラムを作成してみるが、この時点で false が帰る。後日、動かしてみたら true だった。おそらくこれはパーミッションだったかな・・・
これは困った。is_writable の実装を探す旅にでるしかないのかと思ったが、ふと英語が出来ないなりに「is_writable always false」でググったら一番上に出てきた。
selinux... すっかり忘れていた・・・コネクション周りなら思い出せたかもしれなかったが。

# setenforce 0
ついでに、/etc/selinux/config の SELINUX を disabled に変更。
で無事にインストールを続けることができた。

続く...

2011年12月7日水曜日

複数 FLV ファイルから DVD 作成

今回は開発以外で嵌まったことを。
知人に複数 FLV から DVD を作成したいと言われたので調査することに。これが思いのほか嵌まった・・・

そもそも、動画を変換、編集することがかなり久しぶりだった。昔は、DVD-RAM で TV 番組を録画して CM カットして DVD-R に保存なんてこともやっていたが、何年も前であまり覚えていない。
前は、DVD ドライブを買うと、動画編集ソフトやオーサリングソフトがバンドルされていたが、現在手元に何もない・・・なのでフリーソフトでやるしかない。

まず、昔の手順的なものを思い出すことに。たしか、
  1. DVD-RAM(vob たしか中身は mpeg2)に録画
  2. GOP 単位でざっくり CM カット
  3. AVI(huffyuv 可逆圧縮)変換
  4. フレーム単位で細かくカット
  5. mpeg2 に変換
  6. オーサリング
  7. DVD 焼き
みたいなことをやってたはず。途中どっかの手順で音を分離して最後に結合してたような記憶もあるが。
とりあえず、今回は編集が入らないので、
  1. FLV
  2. AVI(huffyuv)に変換
  3. オーサリング(mpeg2 に変換含む)
  4. DVD 焼き
でいけそうだ。

まず、FLV の変換だが、Any Video Converter というソフトでいけそうだ。これで AVI に変換。オーサリングは、Windows7 についてるWindows DVD メーカーを使用した。Windows DVD メーカーは ISO ファイルは作れずに一気に DVD に焼くようだ。
簡単にできたと思い、中身を確認してみると、出た!音ずれだ・・・
そういえば昔も嵌まった・・・だから音を分離して結合してなんて記憶が残ってたわけだ。ちゃんと確認してみると、AVI の時点でずれている・・・先に確認すれば 1 枚無駄にならなかったのに・・・

とりあえず Any Video Converter で変換時に音を分離することにする。で、VirtualDub で結合して AVI の時点で音があってる状態にしてみることに。
ここでさらに問題が。Any Video Converter で作成した AVI(huffyuv) が VirtualDub で開けない。VirtualDub の圧縮の選択肢の中に huffyuv があるというのに。つまりコーデックは入っているということだが。調べてみたら動画再生、作成等の API が 2 種類あるらしい。
  • Video for Windows(コーデックを使用)
  • DirectShow(フィルターを使用)
知っているのは前者のみだったわけで、そういえば ffdshow なるものも入れた気がする。Any Video Converter は両方(?)対応、VirtualDub は前者対応のようだ。
VirtualDub のプラグインで DirectShow を使用するものがあったので入れてみるがうまく認識しなかった。直接 FLV を読み込むプラグインもあるようだったがこれも読み込んでくれない。そもそも、64bit 版の VirtualDub を使っているがプラグインは 32bit 版な気がする。ソース付のもあったのでコンパイルしなおす等もしてみたが、あっているかも分からずやはり認識せず。
仕方ないので、ほかに可逆圧縮はないものかと探したところ、ffv1 とういものが共通で扱えたのでこれでやることに。
で、Any Video Converter で ffv1 を出力後、VirtualDub で読み込み、分離した音を結合した AVI を作成。作成された AVI を見てみると、音がずれている・・・
さらに確認してみると、そもそも、分離した、ffv1 の動画と wav の音の時間がずれている・・・あうわけがない・・・

VirtualDub でどうにかならないかと「オプション」->「音声に同期させる」や「遅れる場合はフレームを落とす」を選択してみたがダメだった。 「音声」->「インターリーブ」あたりを触ってもダメ。
前はどうやっていたか思い出せないが、有料のソフトがいい塩梅でやってくれてたんだろうか。とりあえずさらに調べてみることに。
すると、「映像」->「フレームレート」の「ソースレート調整」->「映像と音声の再生時間が一致するように変更する」という設定があり、これでいけた。

これで映像と音があった AVI ができたので、次は、mpeg2 変換とオーサリングだ。前回みたく失敗するたびに DVD-R が消費されると辛いので、VIDEO_TS 形式なり ISO イメージなりで出力できるアプリケーションを探すことに。mpeg2 に変換できるもの自体が少ないため、選択肢はあまりなく、その中では、メニュー等も作れる DVD forger がよさそうだったのでこれにすることに。

で、またまた問題が。DVD forger は ffv1 形式が読み込めない。かなり振り出しに戻った気分だ。だがここまできてやめるわけにもいかない。すでにかなりの時間を使っている。
Any Video Converter は他の可逆圧縮を選べない。となると、VirtualDub で音の結合をする時点で別形式に変換することに。
可逆圧縮もさほど選択肢がないわけだが、Ut Video Codec YUV が使えたのでこれにする。正直よくわかってないので、ここでも VfW と DirectShow が入り混じっているのかもしれない。

やっと、DVD forger でオーサリングすることに。とりあえずメニューは作らず。DVD forger には音ずれの設定等設定項目があまりないので mpeg2 に変換時に音がずれないでくれと願いつつ、変換 & オーサリングを実行。
確認しみると、おぉ音があってる!後は焼くだけかと、さらっと見てたら動画が途中で終わっている・・・

実は、FLV ファイルは 4 つあって、その 1 つが再生された時点で終わっていた。
ファイルは個々に変換しているので、Ut Video Codec 形式の AVI も 4 つある。それを、DVD forger に追加すると、タイトルが 4 つできる。メニューを作成して、4 つボタンをつけてみると、ボタンクリックからは再生できる。が 1 タイトル終了後メニューに戻ってしまう。次のタイトルが再生できない。見れないことはないのでいいのかも知れないが、美しくない。俺的にアウトだ。
ということで、Ifo Editor なるものを入れて、ifo ファイルを編集することに。
VIDEO_TS.IFO の「VMGM_PGCI_UT」->「LU_1 PGC-Menu_1」の Pre Command や VTS_01_0.IFO の 「VTS_PGCITI」->「VTS_PGC_1」の Pre Command や Post Command をいじってみることに。
(Jump_TT)Jump to Title や(CallSS_VMGM)Call VideoManager PGC など適当にさわってみるが再生されない。メニューにすら飛ばなくなる。PgcEdit のほうがいいという情報も見かけたので入れてみるが変わらない・・・
まったく知識なくいじっているので仕方がないといえば仕方がないが。かと言って IFO の構造を学ぶのも大変そうだ・・・が、もはや意地でやってるので、さらに調べることに。
  • http://www.geocities.jp/montty_jp/backup/index.htm
  • http://dvd.sourceforge.net/dvdinfo/vmi-jmp.html
が、詳しくて参考になった。見てるとどうも、タイトルからタイトルつまり、VTS から VTS には飛べない感じがする。できた VOB ファイルをみると、VTS_01_0.VOB, VTS_02_0.VOB となっていて、VTS_0* の時点で違いがある。これはもしや、VTS_01_0, VTS_01_1 になればいいのかと、DVD forger の設定を見直してみることに。

「Edit videos, audio tracks and subtitles...」から入ったダイアログに「Merge」なるボタンがあるのに気付く。だが押せない。動画を複数選択しても Disable のまま・・・なんのためのボタンだと思いつつ。View のラジオボタンを適当に押していると、「Outline(for re-orderring, merging and deleting titles)」を選択したときに、Enable になった。なんて使いづらいインターフェースだ。View なんて書くと見た目だけ変わるのかと思うじゃね~かと思ったが、よくみりと、ちゃんと書かれている・・・「Outline(for re-orderring, merging and deleting titles)」
英語は苦手だ・・・

とりあえず、4 つ全ての動画を選択して、Merge をクリック。
メニューのボタンが 1 つになったが問題なし。チャプタは?とも思ったが拘りだしてはキリがないし、俺的に拘るところでもないのでスルーすることに。

確認してみるとちゃんと再生された。音が短くそれにあわせた分一番最後が若干さくっと終わる感じはあるが、ご愛嬌ということで。
後は、DeepBurner で DVD に焼いて終了。焼くのはすんなりいった。

久しぶりに動画の編集をやったがやはり大変。昔に比べてマシンスペックはあがっているので、エンコード時間は短いが、それでも数十分、数時間の待ちがあるので、待ったあとダメだった場合が辛い。
まぁ昔は 30 分の動画をエンコードするのに一晩中動かしても終わってなかったりしてたわけだが。

ちなみに著作権が絡む動画は注意が必要。個人的にダウンロードして複製する分には問題なさそうだが、YouTube などはダウンロードの時点で規約違反となる。違法でなければやっていいというわけでもない。モラルの問題もある。
了承を得られている等、著作権的に問題がない動画ならいいが。
本の自炊屋が消えていったりしているので、著作権が絡む動画を今回のように人に頼まれて変換して渡すとなるとアウトな気がする。

長々と書いてて読みにくいことに気付いた。キャプチャ等を貼るべきかと思うがそれもメンドイ。無理やり文字を大きくしたりでなんとかならんかとやってみたが・・・