2.FFmpegとAvisynth
前回に書いたような経緯でffmpeg.exeやavconv.exeでも日本語ファイル名のavsを読めるようになったのだが、今年の3月に今度はFFmpegのほうだけでこれが再発した。原因はこのコミット。
Avxsynthの開発者がAvxsynth入力を導入するべくFFmpegのほうだけavformat/avisynth.cを全部書きなおしてしまったことにより発生したのだった。
そして、自分がバグの再発を知ったのは先月(6月)の半ば頃のことである(2ちゃんねるのffmpegスレで見かけた)。
さて、問題のコードは次のとおりだった。
arg = avs_new_value_string(s->filename); val = avs_library->avs_invoke(avs->env, "Import", arg, 0);このコード、x264のavs.cを参考にしているわけだが、大事なことを忘れている。
前回も書いたように、s->filenameの中身はUTF-8でエンコードされた文字列である。
一方、Avisynthはマルチバイト文字アプリケーションで、文字列はACPエンコードが前提になっている。
だから非ASCIIな文字を含んだ文字列をそのままでAvisynthに渡したら、Avisynthはファイルを見つけられないのである。
書きなおすのは構わないんだけど、できればもうちょっと既存のコードを注意して読んでおいて欲しかった……。
ちょっと腹がたったから言っちゃうけど、Avxsynthユーザーなんて、非英語圏のAvisynthユーザーの千分の一もいないよ。
さて、原因は前回と同じなので対策も前回とまったく同じである。
再びパッチを書いて今度はFFmpegのMLに送った(Avxsynthの中の人はFFmpegだけに送ったのでLibavは昔のまま)。
かくしてコードは次のように変わった。
#ifdef _WIN32 char filename_ansi[MAX_PATH * 4]; wchar_t filename_wc[MAX_PATH * 4]; MultiByteToWideChar(CP_UTF8, 0, s->filename, -1, filename_wc, MAX_PATH * 4); WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi, MAX_PATH * 4, NULL, NULL); arg = avs_new_value_string(filename_ansi); #else arg = avs_new_value_string(s->filename); #endif val = avs_library->avs_invoke(avs->env, "Import", arg, 0);変数名が変わったのと MAX_PATH * 4 は、そのほうがいいんじゃね?とレビューしてもらったDaemon404(Derek Builtenhuis)氏に言われたから。
さすがにもう再発することはないと思うけど、もし再発しても次は知らない。気づいた人が直して下さい。
(そもそも筆者はエンコード素材のファイル名は半角英数以外使わないので、自分で気づくことはまずありません)
それともうひとつ。
このFFmpegの新Avisynth入力は、Avisynth2.5.8では不具合が出るそうです(参考:avisynth scripts fail to load in ffmpeg)。
まだ2.5.8を使ってる人は、とっとと2.6alphaに更新しましょう。
0 件のコメント:
コメントを投稿