S.F. Page

Programming,Music,etc...

ffmpegをVS2015 CTPでコンパイルしてみる (6)

最後のエラーについて対処しようとしている。どんなエラーが発生しているかというと

ffmpeg.c(395): error C2039: '_cnt': is not a member of '_iobuf'

である。_iobuf構造体に_cntメンバーがないのでエラーが発生している。エラーはread_key関数で発生している。そこだけコードを抜き出すと

となっていて、上記の32行目でエラーが発生している。stdinは_iobufのエイリアスである。VS2015の_iobufはvoid*のエイリアスとなっており、そのためエラーが発生しているのである。これはどうすればよいのか。

この関数はそもそもノン・ブロッキングにキーコードを1文字分読みだすためのものである。C言語ではノン・ブロッキングにキーコードを読みだすには一工夫必要でこのような関数を用意する必要があるのだ。でエラー部分のifブロックは何かというと、入力バッファにデータが1文字以上入っていたら、read関数で標準入力から1文字データを読み出すというコードである。read関数はブロッキングするのでこのようなハックが必要となる。ちなみにread関数の第一引数はハンドルであるが、これを0に設定すると標準入力(stdin)から読み出すことになるらしい。この書き方はそこそこ有名なものらしい。

しかしこの関数にはもう一つ、ノンブロッキングに標準入力からキー入力を読み出すコードがある。それが52-3行目のコードである。kbhit関数はキー入力があったかどうかをノンブロッキングにチェックする関数である。これでキー入力の有無を判定してから、キー入力があればgetch関数で読み出すというコードとなっている。getchはやはりブロッキングするので、このようなハックが必要なのである。

その他は名前付きパイプからのキーコード読み取りなのでこれはまあいいとして標準入力からのキーコード読み取りコードがそもそも重複しているようである。なので最初のstdin->_cntチェックによるキーコード読み出しは不要な気がする。

で、VS2015になってからなぜ_iobufがvoid*に変わったのかというと、まだはっきりとしていないがこれが正しい実装らしい。どうも_iobufはFILE構造体のエイリアスであったのがvoid*に変更になったようである。まだはっきりとした確証はないが。そこでvoid*をFILE構造体にキャストすればいいのではと思ったりもするがこれはどうなのだろうか。ffmpegメーリングリストにも以下のようなポストがあった。

The old "stdin->_cnt" hack no longer works since "FILE" in the new C runtime is just a struct with a void*.

[FFmpeg-devel] [PATCH] Make compilable with VS2015

C99の規格を少しのぞいてみようかなと思っている。