2011年7月22日金曜日

flacをなんとか2GB以上のファイルを吐き出すようにする

少し前にCDをひとまとめにする方法を書きましたが、
flacでなぜか2GBでとまってしまうという現象の原因がわかりました。

まあ原因そのものは割りとすぐにわかって、fseek/ftellのポインタサイズが
32ビットなのが原因です。約2GB分のオフセットしか表現できないことになります。

通常のオフセットの型は符号付整数longで、コンパイラ依存ですがgccでもVCでも
4byteになります。これを64ビット対応したfseeko64/ftello64にして、
引数のオフセット変数の宣言をlong long型にしてやれば解決なのですが・・・

本来-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64をgccに
渡してあげればいいようなのですが、どうも適用になっていないようです。

なのでconfigureに渡すパラメータとソースファイルの調整が必要になります。

以下、Xiph.orgのflac1.2.1のソースコードとMinGW64の環境で実験しております。

①off_t型の強制書き換え
sys/types.hを見てもらえばわかるように、オフセットのoff_tもしくは
_off_t型はlongで宣言されています。
これをプリプロセスの時点でoff64_tに上書きします。
いちいちソースファイルに#DEFINEを書く必要はありません。
CFLAGSなどにセットするだけで書き換えができます。
./configure --prefix=/usr/local --enable-sse \
--disable-shared --enable-static \
--disable-xmms-plugin -with-ogg=/usr/local \
CFLAGS="-D_off_t=_off64_t -Doff_t=off64_t -D_OFF_T_DEFINED -D_OFF_T_" \
CPPFLAGS="-D_off_t=_off64_t -Doff_t=off64_t -D_OFF_T_DEFINED -D_OFF_T_" \
CXXFLAGS="-D_off_t=_off64_t -Doff_t=off64_t -D_OFF_T_DEFINED -D_OFF_T_" \
FFLAGS="-D_off_t=_off64_t -Doff_t=off64_t -D_OFF_T_DEFINED -D_OFF_T_"

長いので自分はスクリプトにしてbashに渡しています。
ちなみに環境はWindows7HomePremium(x64)で、MinGWはx86_64の環境です。
MinGW32(pc-i686)だとtypes.hが微妙に違ったりするので、マクロの構成は
自前で確認してください。

やってることはoff_tの書き換えと、off_tの定義済みフラグを立てることです。

②fseek/ftellのマクロ修正
64ビット対応したfseeko64/ftello64に置き換えるようプリアンブルのマクロを
修正します。基本セットはfseeko/ftelloになっているので
環境に合わせて分岐させればいいです。
ちなみにVC++2010ではfseeki64/ftelli64というメソッドが用意されてます。

記述するとえらいことになるのでpatchを用意しました。
ファイルはこちら

それでもってmakeすると(ウチの環境では)64bitのflacの出来上がりです。
2GBの制限もきれいさっぱりなくなりました。
なぜかnasm通すとエラーになりますが(汗

あ、あと調査の中でわかったのは、fseekのオフセットはフロントエンドに
依存するっぽいです。元のソースのまんまでもライブラリを
直接叩くようなアプリならちゃんと2GB超えても作成できました。
ぶっちゃけWinampなんですが。

VisualC++2010でも無理やりビルドして動作するのを確認はしましたが・・・
いかんせん、疲れた。

0 件のコメント:

コメントを投稿