/*
 *	app.c
 *
 *	Sofdec2EncHelper.exe - sofdec2enc.exeヘルパー
 *	Copyright (C) 2016-2018 Naoyuki Sawa
 *
 *	* Wed Aug 24 21:05:06 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	  sofdec2enc.exeはパーセンテージ指定のスケーリングが出来ないので、補助ツールとして当ツールを作成しました。
 *	  また、sofdec2enc.exeはオプション指定が複雑なので、簡略化するために当ツールを作成しました。
 *	  詳細は、usage()を参照して下さい。
 *	* Wed Aug 31 23:56:52 JST 2016 Naoyuki Sawa
 *	- '-h'オプションで表示される'USAGE:'のプログラム名が間違っていたので、修正しました。
 *	  ツールの動作には、変更有りません。
 *	* Fri Sep 09 21:13:53 JST 2016 Naoyuki Sawa
 *	- '-o'オプションを追加しました。
 *	  これまでは、'入力ファイル名.usm'というファイル名でしか出力出来ませんでしたが、今後は、入力ファイルと異なる名前でも出力出来るようになりました。
 *	- '-q'オプションに、'-qオプション文字列'形式を追加しました。
 *	  このオプションを追加した目的は、'-q1'と'-q2'の差が大きすぎて、'-qmf_range'等を明示的にもう少し細かく調整したいケースが生じたからです。
 *	* Tue Dec 20 21:28:56 JST 2016 Naoyuki Sawa
 *	- ライブラリをバージョンアップした事に伴い、/clip/tool/SofdecHelper/ をリビルドした事に伴い、当ツールもリビルドしました。
 *	  当ツールのソースコード,及び,当ツールの動作には変更有りません。
 *	* Thu Dec 22 09:49:41 JST 2016 Naoyuki Sawa
 *	- ライブラリをバージョンアップした事に伴い、/clip/tool/SofdecHelper/ をリビルドした事に伴い、当ツールもリビルドしました。
 *	  当ツールのソースコード,及び,当ツールの動作には変更有りません。
 *	* Fri Dec 30 21:09:49 JST 2016 Naoyuki Sawa
 *	- 入力ファイル名のサフィックスによる自動スケーリング指定に対応しました。
 *	  関連する処理は、/clip/test.win/grp/MkTexNo.batの'Sat Sep 10 21:46:35 JST 2016'のコメント、及び、/clip/DxlibHelper.cppの'Sat Sep 10 21:46:35 JST 2016'のコメントを参照して下さい。
 *	  具体的には、以下の通りです。
 *	- これまでは、個々のプロジェクトのバッチスクリプトで、ムービーをエンコードする時にファイル名のサフィックスを判断してサイズオプションを指定していました。
 *	  しかし、入力ファイル名のサフィックスをラベルから削除する処理は既に/clip/test.win/grp/MkTexNo.batに含めてあるし、実行時の自動スケーリング処理は既に/clip/DxlibHelper.cppに含めてあるのに、
 *	  ファイル名のサフィックスを判断する処理だけが個々のプロジェクトのバッチスクリプトに依存するのは、統一性が無くて管理しづらいと思いました。
 *	  そこで、ファイル名のサフィックスを判断する処理も当ツールに含める事にしました。(以前からそうすべきだとは思っていたのですが、対応が遅れていただけです…)
 *	* Mon May 08 08:35:51 JST 2017 Naoyuki Sawa
 *	- ライブラリのバグ修正に伴う、ツールのリビルドを行いました。
 *	  詳細は、clipmisc.cの'Sun May 07 09:13:01 JST 2017 Naoyuki Sawa'のコメントを参照して下さい。
 *	* Fri May 12 09:53:14 JST 2017 Naoyuki Sawa
 *	- 入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
 *	- '-a2'をデフォルトとした理由は、一般的には、加算テクスチャはアルファ無しとする方が良いからです。
 *	  サフィックス'-add'を含んでいると、'dTexDefC.exe -a'によって加算テクスチャとして使うのが一般的だと思います。
 *	  加算テクスチャとして使う場合は、普通は、アルファ無しaviとして出力しているはずなのですが、稀に、うっかりアルファ付きaviで出力してしまう事が有ります。
 *	  見た目にはされでも問題無いのですが、アルファ付き動画はデコードが重く、極端に負荷が上がってしまう問題が生じます。
 *	  本来は、アルファ無しでデコードして加算すれば低負荷で済むところ、アルファ付きでデコードする無駄が生じているわけです。
 *	  そこで、サフィックス'-add'を含んでいる、加算テクスチャと思わしきaviは、強制的にアルファ無しでエンコードする動作をデフォルトとする事にしました。
 *	- ただし、意図的に、アルファ付き加算テクスチャを作成するケースが、無いとは言い切れません。
 *	  加算テクスチャの加算したくない色の部分をアルファ0にして、実行時にアルファを掛けた後に加算するようなテクスチャです。
 *	  そのようなテクスチャは作り方としては無駄であり、プレマルチプライドにしてアルファに非依存にすべきなのですが、そういう素材が無いとは限りません。
 *	  そのような素材を使わざるを得ない場合のみ、'-a1'を指定して、サフィックス'-add'を含んでいてもアルファ付きでエンコードするようにして下さい。
 *	* Tue May 16 21:50:27 JST 2017 Naoyuki Sawa
 *	- '-q数値'オプションの定義を変更しました。
 *	  変更前は、数値の範囲は0～2でしたが、変更後は、数値の範囲が0～9で、より細かく指定出来るようにしました。
 *	  変更した理由は、以下の通りです。
 *	- 変更前は'-q1'と'-q2'の画質の差が大き過ぎて、その中間を指定するために'-q文字列'形式で指定せざるを得ないケースが頻繁に発生しました。
 *	  簡単に指定出来るように'-q数値'形式を設けていたのに、実際には'-q文字列'形式を使わざるを得ないのでは'-q数値'形式をを設けた意味が無いので、実際に'-q数値'形式を使えるように'-q数値'の定義を変える事にしました。
 *	- 変更前と変更後の対応は、以下の通りです。
 *	  ・変更前の'-q0' ⇒ 変更後の'q0' (変わっていません)
 *	  ・変更前の'-q1' ⇒ 変更後の'q1' (変わっていません)
 *	  ・変更前の'-q2' ⇒ 変更後の'q9'
 *	- 変更後は、'-q2'～'-q8'の間で、細かく画質を調整出来るようにしました。
 *	  '-q2'～'-q8'の違いは、sofdec2enc.exeに対する「-qmf_range」の違いだけで、「-bitrate」「-br_range」「-alpha_quality」は最低画質固定としました。
 *	  そうした理由は、実際に試した所、「-bitrate」「-br_range」「-alpha_quality」を変えてもさほど画質の違いは感じられず、「-qmf_range」だけで調整するのが判り易くて良いと思ったからです。
 *	  「-qmf_range」の設定が、0.0から1.0は0.25刻み,及び,0.5刻みで、それ以上は1.0刻みとした理由は、'-q数値'オプションの数値を一桁に収めたかったからです。
 *	  実際の所、高画質の範囲で細かく調整したいケースよりも、低画質の範囲で細かく調整したいケースの方が多いと思うので、この刻みで良いと思います。
 *	- '-q数値'形式で「-hcfilter=ON」になるのは、'-q0'のみとしました。
 *	  「-hcfilter=ON」にすると極端に画質が悪く、エンコード時間も長くなるので、実際の所、'-q0'を使う事は無いと思います。
 *	  '-q0'はあくまでも、これ以下は無いという理論上の最低画質を検証するためだけに、用意した設定です。
 *	  従って、'q1'以上では、「-hcfilter=ON」になる設定は設けていません。
 *	  もし、「-hcfilter=ON」を使いたい場合は、'-q文字列'形式を使って、明示的に指定して下さい。
 *	- デフォルトの画質を変更しました。
 *	  変更前は、デフォルトは'-q1'としていましたが、変更後は、デフォルトは'-q9'(変更前の'-q2'に相当)としました。
 *	  Sofdec2EncHelper.exeに対して何も指定しなければ、sofdec2enc.exeに対して何も指定しない時と同じ画質(=高画質)になる方が、自然だと思ったからです。
 *	* Tue May 16 22:53:42 JST 2017 Naoyuki Sawa
 *	- '-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
 *	  <例>
 *	  ・「Sofdec2EncHelper.exe     foo-q1.avi」⇒品質1でエンコードします。
 *	  ・「Sofdec2EncHelper.exe -q2 foo-q1.avi」⇒'-q'オプションよりもサフィックスが優先され、品質1でエンコードします。
 *	  ・「Sofdec2EncHelper.exe -Q2 foo-q1.avi」⇒'-Q'オプションがサフィックスよりも優先され、品質2でエンコードします。
 *	* Wed May 17 21:36:23 JST 2017 Naoyuki Sawa
 *	- サフィックスを厳密に検査するようにしました。
 *	  具体的には、以下の通りです。
 *	- これまでは、「ファイル名の中に文字列が有るか」という手抜きの方法で検査していたので、意図したサフィックスを含まないファイル名にも一致してしまう可能性が有りました。
 *	  例えば、"foo-address.avi"というファイル名は、サフィックス'-add'を含んでいませんが、間違ってサフィックス'-add'を含むと判断してしまっていました。
 *	  実際には、上記のようなファイル名を使う事はまず無いので、これまでの方法でも実用上は問題無かったのですが、万一、問題となる可能性も内包していました。
 *	  そこで今回、サフィックスを厳密に検査するように修正しました。
 *	  今後は、"foo-address.avi"が間違ってサフィックス'-add'に一致してしまうような、問題は生じません。
 *	  また、今回の修正に合わせて、同じサフィックスを複数含んだ場合もエラーにするように検査を追加しました。
 *	  例えば、"foo-2x-3x.avi"は、スケーリングのサフィックスを複数含んでいるので、エラーと見なします。
 *	* Wed Jul 19 21:57:38 JST 2017 Naoyuki Sawa
 *	- サフィックス'-a0～2'を追加しました。
 *	  コマンドラインオプションによる'-a0～2'指定よりも優先され、コマンドラインオプションによる'-a0～2'指定をオーバーライドする事が出来ます。
 *	  このサフィックスを追加した理由は、アルファ不要な背景用ムービーなのにアルファ付きで作成されているaviが有り、バッチ変換の際にそのaviだけ強制的にアルファ無しとしたい要件が発生したからです。
 *	  既に、'アルファ不要な加算用ムービーなのにアルファ付きで作成されているaviに対して強制的にアルファ無しとする対策'は、サフィックス'-add'によって対応済み('Fri May 12 09:53:14 JST 2017 Naoyuki Sawa'コメント参照)なのですが、
 *	  '背景用ムービ'ーに対しても同様の問題が生じたので、新たにサフィックス'-a0～2'を追加する事にしました。
 *	  <例> (has_alpha.aviがアルファ付きaviであると仮定します。)
 *	  │Sofdec2EncHelper.exe     has_alpha-a0.avi		アルファ付きでエンコードします。コマンドラインオプション'-a0～2'を指定していないので、デフォルトで'-a2'と同じですが、サフィックス'-a0'が優先されるからです。	←←←今回、サフィックス'-a0～2'を追加した主目的は、こういう使い方をするためです。これ以下の例は実際に使う事は稀だと思いますが、一応、挙げておきます。
 *	  │Sofdec2EncHelper.exe     has_alpha.avi		アルファ付きでエンコードします。コマンドラインオプション'-a0～2'を指定していないので、デフォルトで'-a2'と同じです。
 *	  │Sofdec2EncHelper.exe -a0 has_alpha.avi		アルファ無しでエンコードします。
 *	  │Sofdec2EncHelper.exe -a0 has_alpha-a1.avi		アルファ付きでエンコードします。コマンドラインオプション'-a0'よりも、サフィックス'-a1'が優先されるからです。
 *	  │Sofdec2EncHelper.exe -a0 has_alpha-a2.avi		アルファ付きでエンコードします。コマンドラインオプション'-a0'よりも、サフィックス'-a2'が優先されるからです。
 *	  │Sofdec2EncHelper.exe -a0 has_alpha-a2-add.avi	アルファ無しでエンコードします。コマンドラインオプション'-a0'よりも、サフィックス'-a2'が優先され、かつ、'-add'サフィックスによってアルファ無しと判断されるからです。
 *	  │Sofdec2EncHelper.exe -a1 has_alpha-a2-add.avi	アルファ無しでエンコードします。コマンドラインオプション'-a1'よりも、サフィックス'-a2'が優先され、かつ、'-add'サフィックスによってアルファ無しと判断されるからです。
 *	* Thu May 03 23:59:59 JST 2018 Naoyuki Sawa
 *	- Boehm GCを修正した事に伴い、当ツールもリビルドしました。
 *	  詳細は、/clip/tool/gc/README.TXTの'Wed May 02 23:59:59 JST 2018 Naoyuki Sawa'のコメントを参照して下さい。
 */
#include "app.h"
#define VERSION		"20180503"	//最終更新日
/****************************************************************************
 *	main
 ****************************************************************************/
int main(int argc, char* argv[]) {
	int exitCode = EXIT_SUCCESS;
#ifdef  _DEBUG
	remove("syslog.out");			//毎回ログを削除する事にした。
    #ifndef USE_JOB_DEBUG
	openlog(NULL, LOG_PERROR, LOG_USER);	//デバッグビルドでは、システムログを標準エラーにも出力する。ただし、デバッグジョブを使用する場合は、デバッグジョブのcurses表示と衝突しないよう、標準エラーには出力しない。
    #endif//USE_JOB_DEBUG
#else //_DEBUG
	setlogmask(LOG_UPTO(LOG_INFO));		//リリースビルドでは、LOG_DEBUGを抑制する。
#endif//_DEBUG
#if     (defined(GC_H) && !defined(USE_BISON_FLEX))
//	putenv("GC_LOG_FILE=CON");//ログ出力先を指定する。
//	GC_set_find_leak(1);//メモリリーク検出を開始する。
#endif//(defined(GC_H) && !defined(USE_BISON_FLEX))
#ifdef  __CLIP_SEH_H__
	SEH_init();
#endif//__CLIP_SEH_H__
	app_init(argc, argv);
	exitCode = app_main(argc, argv);
	app_exit();
#if     (defined(GC_H) && !defined(USE_BISON_FLEX))
//	CHECK_LEAKS();//メモリリークを検出する。
#endif//(defined(GC_H) && !defined(USE_BISON_FLEX))
	return exitCode;
}
/****************************************************************************
 *	usage
 ****************************************************************************/
#define SOFDEC2ENC_DEFAULTPATH	"C:\\cri\\tools\\Sofdec2\\sofdec2enc.exe"
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
__declspec(noreturn) static void usage() {
	fprintf(stderr, "Sofdec2EncHelper.exe - sofdec2enc.exeヘルパー (%s)\n", VERSION);
	fprintf(stderr, "Copyright (C) 2016-2018 Naoyuki Sawa\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "USAGE:\n");
	fprintf(stderr, "  Sofdec2EncHelper.exe [option ...] [aviファイル名 ...]\n");
	fprintf(stderr, "  ・aviファイル名は、ワイルドカードによる複数指定も可能です。\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "OPTIONS:\n");
	fprintf(stderr, "    -o出力ファイル名    出力ファイル名をフルパスで指定します。\n");
	fprintf(stderr, "                        このオプションを指定しなければ、'入力ファイル名.usm'で出力します。\n");
	fprintf(stderr, "                        入力ファイルに、複数のaviファイルを指定した場合は、このオプションを指定してはいけません。\n");
	fprintf(stderr, "    -w横ピクセル数      <例> -w128     横サイズを128ピクセルにスケーリングします。\n");
	fprintf(stderr, "    -w横拡大率%%         <例> -w200%%    横サイズを入力画像の200%%にスケーリングします。\n");
	fprintf(stderr, "    -w分子/分母         <例> -w128/640 横サイズを128/640の割合でスケーリングします。\n");
	fprintf(stderr, "    -h縦ピクセル数      <例> -h88      縦サイズを88ピクセルにスケーリングします。\n");
	fprintf(stderr, "    -h縦拡大率%%         <例> -h75%%     縦サイズを入力画像の75%%にスケーリングします。\n");
	fprintf(stderr, "    -h分子/分母         <例> -w88/480  縦サイズを88/480の割合でスケーリングします。\n");
	fprintf(stderr, "    -s縦横ピクセル数    <例> -s256     縦横サイズを256ピクセルにスケーリングします。\n");
	fprintf(stderr, "    -s縦横拡大率%%       <例> -s50%%     縦横サイズを入力画像の50%%にスケーリングします。\n");
	fprintf(stderr, "    -s分子/分母         <例> -s2/3     縦横サイズを2/3の割合でスケーリングします。\n");
//{{2017/05/16変更:'-q数値'オプションの定義を変更しました。
//	fprintf(stderr, "    -q0                 最低画質でエンコードします。\n");
//	fprintf(stderr, "    -q1                 低画質でエンコードします。(デフォルト)\n");
//	fprintf(stderr, "    -q2                 高画質でエンコードします。\n");
//↓2017/05/16変更:'-q数値'オプションの定義を変更しました。
	fprintf(stderr, "    -q0～9              0(低画質)～9(高画質)でエンコードします。\n");
//}}2017/05/16変更:'-q数値'オプションの定義を変更しました。
	fprintf(stderr, "    -qオプション文字列  sofdec2enc.exeの任意のオプションを直接指定します。複数指定する場合は\"～\"で囲って下さい。\n");
//{{2017/05/16追加:'-q数値'オプションの定義を変更しました。
	fprintf(stderr, "                        '-q0～9'も'-qオプション文字列'も指定しなければ、'-q9'を指定したのと同じ動作となります。(デフォルト)\n");
//}}2017/05/16追加:'-q数値'オプションの定義を変更しました。
//{{2017/05/16追加:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
	fprintf(stderr, "    -Q0～9              ┐'-q0～9',及び,'-qオプション文字列'と同じですが、ファイル名サフィックスによる品質指定よりも優先されます。\n");
	fprintf(stderr, "    -Qオプション文字列  ┘詳細は、後述の説明を参照して下さい。\n");
//}}2017/05/16追加:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
//{{2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
//	fprintf(stderr, "    -a0                 アルファ無しでエンコードします。\n");
//	fprintf(stderr, "    -a1                 アルファ付きでエンコードします。ただしアルファ無しaviの場合は無視されます。(デフォルト)\n");
//↓2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
	fprintf(stderr, "    -a0                 アルファ無しでエンコードします。\n");
	fprintf(stderr, "    -a1                 アルファ付きでエンコードします。ただしアルファ無しaviの場合は無視されます。\n");
	fprintf(stderr, "    -a2                 ファイル名の中に'-add'が含まれていたら'-a0'と同じ動作、含まれていなければ'-a1'と同じ動作となります。(デフォルト)\n");
//}}2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
//{{2017/07/19追加:サフィックス'-a0～2'を追加しました。
	fprintf(stderr, "                        '-a0～2'オプションと同じ効果は、ファイル名サフィックス'-a0～2'によって指定する事も可能です。\n");
	fprintf(stderr, "                        '-a0～2'オプションと、ファイル名サフィックス'-a0～2'が両方指定された場合、ファイル名サフィックスが優先されます。\n");
//}}2017/07/19追加:サフィックス'-a0～2'を追加しました。
	fprintf(stderr, "    -pツールのパス名    sofdec2enc.exeのフルパス名を指定します。(デフォルト=%s)\n", SOFDEC2ENC_DEFAULTPATH);
	fprintf(stderr, "    -v                  コマンドライン文字列と終了ステータスを表示します。\n");
	fprintf(stderr, "    -n                  コマンドライン文字列だけを表示し、コマンドを実行しません。\n");
	fprintf(stderr, "    -h                  使い方を表示します。\n");
//{{2016/12/30追加:入力ファイル名のサフィックスによる自動スケーリング指定に対応しました。
	fprintf(stderr, "\n");
	fprintf(stderr, "    ファイル名サフィックスによる、自動スケーリング指定も可能です。\n");
	fprintf(stderr, "    ・ファイル名の中に'-1x'～'-9x'が含まれていたら、サイズオプション'-s1/1'～'-s1/9'が指定されたのと同じと見なします。\n");
	fprintf(stderr, "    ・明示的なサイズオプション指定は、ファイル名サフィックスによる自動スケーリング指定よりも優先されます。\n");
//}}2016/12/30追加:入力ファイル名のサフィックスによる自動スケーリング指定に対応しました。
//{{2017/05/16追加:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
	fprintf(stderr, "\n");
	fprintf(stderr, "    ファイル名サフィックスによる、品質指定も可能です。\n");
	fprintf(stderr, "    ・ファイル名の中に'-q0'～'-q9'が含まれていたら、品質オプション'-q0'～'-q9'が指定されたのと同じと見なします。\n");
	fprintf(stderr, "    ・明示的な品質オプション'-q～'は、ファイル名サフィックスによる品質オプションによって上書きされます。\n");
	fprintf(stderr, "    ・明示的な品質オプション'-Q～'は、ファイル名サフィックスによる品質オプションを上書きします。\n");
//}}2017/05/16追加:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
	fprintf(stderr, "\n");
	fprintf(stderr, "EXAMPLE:\n");
	fprintf(stderr, "    ①Sofdec2EncHelper.exe -s50%% -q0 -pC:\\usr\\bin\\sofdec2enc.exe *.avi\n");
	fprintf(stderr, "      カレントフォルダに有る全てのaviファイルを、50%%にスケーリングして最低画質でエンコードします。\n");
	fprintf(stderr, "      sofdec2enc.exeが、C:\\usr\\bin\\sofdec2enc.exeに存在するものとします。\n");
	fprintf(stderr, "    ②Sofdec2EncHelper.exe -q\"-bitrate=0 -br_range=0,0 -qmf_range=0.0,2.5 -alpha_quality=0\" -oOut\\Output.usm In\\Input.avi\n");
	fprintf(stderr, "      In\\Input.avi.aviをエンコードして、Out\\Output.usmを出力します。\n");
//{{2017/05/16変更:'-q数値'オプションの定義を変更しました。
//	fprintf(stderr, "      品質オプションを明示的に指定して、'-q1'と'-q2'の中間位の品質とします。\n");
//↓2017/05/16変更:'-q数値'オプションの定義を変更しました。
	fprintf(stderr, "      品質オプションを明示的に指定して、'-q5'と'-q6'の中間位の品質とします。\n");
//}}2017/05/16変更:'-q数値'オプションの定義を変更しました。
	exit(EXIT_FAILURE);
}
/****************************************************************************
 *	
 ****************************************************************************/
void app_init(int argc, char* argv[]) {
//{{アプリケーション特有の処理
	{
		/** no job **/
	}
//}}アプリケーション特有の処理
}
/*--------------------------------------------------------------------------*/
void app_exit() {
//{{アプリケーション特有の処理
	{
		/** no job **/
	}
//}}アプリケーション特有の処理
}
/*--------------------------------------------------------------------------*/
//\clip\tool\dpbmppp\dpbmppp.cを元にして作成しました。
int opt_w1;			//幅指定
int opt_w2;			//  指定無し      w1=0         , w2=0
				//  ピクセル指定  w1=ピクセル数, w2=0
				//  %指定         w1=%         , w2=100
				//  分数指定      w1=分子      , w2=分母
				//  (どの場合も、解析後に分子/分母に設定し直します)
int opt_h1;			//高さ指定
int opt_h2;			//  (opt_w1,w2と同様。上コメントを参照してください)
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//{{2017/05/16変更:'-q数値'オプションの定義を変更しました。
//#define Q_0	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,0.0 -alpha_quality=0 -hcfilter=ON"	//0=最低画質
//#define Q_1	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,0.0 -alpha_quality=0"			//1=低画質
//#define Q_2	""										//2=高画質
//const char* const TBL_q[]={Q_0,Q_1,Q_2};
//const char* opt_q = Q_1;	//品質オプション。実際には、この文字列をsofdec2enc.exeへそのまま引き渡すので、'-qオプション文字列'形式で指定すれば、品質以外のオプションも指定可能です。
//↓2017/05/16変更:'-q数値'オプションの定義を変更しました。
// * Tue May 16 21:50:27 JST 2017 Naoyuki Sawa
// - '-q数値'オプションの定義を変更しました。
//   変更前は、数値の範囲は0～2でしたが、変更後は、数値の範囲が0～9で、より細かく指定出来るようにしました。
//   変更した理由は、以下の通りです。
// - 変更前は'-q1'と'-q2'の画質の差が大き過ぎて、その中間を指定するために'-q文字列'形式で指定せざるを得ないケースが頻繁に発生しました。
//   簡単に指定出来るように'-q数値'形式を設けていたのに、実際には'-q文字列'形式を使わざるを得ないのでは'-q数値'形式をを設けた意味が無いので、実際に'-q数値'形式を使えるように'-q数値'の定義を変える事にしました。
// - 変更前と変更後の対応は、以下の通りです。
//   ・変更前の'-q0' ⇒ 変更後の'q0' (変わっていません)
//   ・変更前の'-q1' ⇒ 変更後の'q1' (変わっていません)
//   ・変更前の'-q2' ⇒ 変更後の'q9'
// - 変更後は、'-q2'～'-q8'の間で、細かく画質を調整出来るようにしました。
//   '-q2'～'-q8'の違いは、sofdec2enc.exeに対する「-qmf_range」の違いだけで、「-bitrate」「-br_range」「-alpha_quality」は最低画質固定としました。
//   そうした理由は、実際に試した所、「-bitrate」「-br_range」「-alpha_quality」を変えてもさほど画質の違いは感じられず、「-qmf_range」だけで調整するのが判り易くて良いと思ったからです。
//   「-qmf_range」の設定が、0.0から1.0は0.25刻み,及び,0.5刻みで、それ以上は1.0刻みとした理由は、'-q数値'オプションの数値を一桁に収めたかったからです。
//   実際の所、高画質の範囲で細かく調整したいケースよりも、低画質の範囲で細かく調整したいケースの方が多いと思うので、この刻みで良いと思います。
// - '-q数値'形式で「-hcfilter=ON」になるのは、'-q0'のみとしました。
//   「-hcfilter=ON」にすると極端に画質が悪く、エンコード時間も長くなるので、実際の所、'-q0'を使う事は無いと思います。
//   '-q0'はあくまでも、これ以下は無いという理論上の最低画質を検証するためだけに、用意した設定です。
//   従って、'q1'以上では、「-hcfilter=ON」になる設定は設けていません。
//   もし、「-hcfilter=ON」を使いたい場合は、'-q文字列'形式を使って、明示的に指定して下さい。
// - デフォルトの画質を変更しました。
//   変更前は、デフォルトは'-q1'としていましたが、変更後は、デフォルトは'-q9'(変更前の'-q2'に相当)としました。
//   Sofdec2EncHelper.exeに対して何も指定しなければ、sofdec2enc.exeに対して何も指定しない時と同じ画質(=高画質)になる方が、自然だと思ったからです。
#define Q_0	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,0.0  -alpha_quality=0 -hcfilter=ON"
#define Q_1	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,0.0  -alpha_quality=0"			//"-hcfilter=AUTO"相当
#define Q_2	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,0.25 -alpha_quality=0"			//"-hcfilter=AUTO"相当
#define Q_3	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,0.5  -alpha_quality=0"			//"-hcfilter=AUTO"相当
#define Q_4	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,1.0  -alpha_quality=0"			//"-hcfilter=AUTO"相当
#define Q_5	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,2.0  -alpha_quality=0"			//"-hcfilter=AUTO"相当
#define Q_6	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,3.0  -alpha_quality=0"			//"-hcfilter=AUTO"相当
#define Q_7	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,4.0  -alpha_quality=0"			//"-hcfilter=AUTO"相当
#define Q_8	"-bitrate=0 -br_range=0,0 -qmf_range=0.0,5.0  -alpha_quality=0"			//"-hcfilter=AUTO"相当
#define Q_9	""										//"-bitrate=3000000 -br_range=0,3000000 -qmf_range=0.0,5.0 -alpha_quality=100 -hcfilter=AUTO"相当
const char* const TBL_q[]={Q_0,Q_1,Q_2,Q_3,Q_4,Q_5,Q_6,Q_7,Q_8,Q_9};
//{{2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
//const char* opt_q = Q_9;	//品質オプション。実際には、この文字列をsofdec2enc.exeへそのまま引き渡すので、'-qオプション文字列'形式で指定すれば、品質以外のオプションも指定可能です。
//↓2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
const char* opt_q;		//品質オプション。実際には、この文字列をsofdec2enc.exeへそのまま引き渡すので、'-qオプション文字列'形式で指定すれば、品質以外のオプションも指定可能です。
int opt_Q;			//opt_qの文字列が、'-q'オプションによって設定されたものならば、opt_Q=0のままとします。opt_qの文字列が、'-Q'オプションによって設定されたものならば、opt_Q=1とします。
//}}2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
//}}2017/05/16変更:'-q数値'オプションの定義を変更しました。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//{{2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
//int opt_a = 1;			//0=アルファ無し,1=アルファ付き。
//				//ただし、アルファ付きを指定しても、アルファ無しaviだったならば、sofdec2enc.exeが無視して、エラーにもならず安全なので、デフォルトでアルファ付きとしました。
//				//特別なケースとして、アルファ付きaviでも、確実にアルファ無しusmを出力したい場合のみ、'-a0'オプションを指定して下さい。
//↓2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
// * Fri May 12 09:53:14 JST 2017 Naoyuki Sawa
// - 入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
// - '-a2'をデフォルトとした理由は、一般的には、加算テクスチャはアルファ無しとする方が良いからです。
//   サフィックス'-add'を含んでいると、'dTexDefC.exe -a'によって加算テクスチャとして使うのが一般的だと思います。
//   加算テクスチャとして使う場合は、普通は、アルファ無しaviとして出力しているはずなのですが、稀に、うっかりアルファ付きaviで出力してしまう事が有ります。
//   見た目にはされでも問題無いのですが、アルファ付き動画はデコードが重く、極端に負荷が上がってしまう問題が生じます。
//   本来は、アルファ無しでデコードして加算すれば低負荷で済むところ、アルファ付きでデコードする無駄が生じているわけです。
//   そこで、サフィックス'-add'を含んでいる、加算テクスチャと思わしきaviは、強制的にアルファ無しでエンコードする動作をデフォルトとする事にしました。
// - ただし、意図的に、アルファ付き加算テクスチャを作成するケースが、無いとは言い切れません。
//   加算テクスチャの加算したくない色の部分をアルファ0にして、実行時にアルファを掛けた後に加算するようなテクスチャです。
//   そのようなテクスチャは作り方としては無駄であり、プレマルチプライドにしてアルファに非依存にすべきなのですが、そういう素材が無いとは限りません。
//   そのような素材を使わざるを得ない場合のみ、'-a1'を指定して、サフィックス'-add'を含んでいてもアルファ付きでエンコードするようにして下さい。
int opt_a = 2;			//0=アルファ無し,1=アルファ付き,2=サフィックスによって選択する。
				//サフィックスに影響されず確実にアルファ無しusmを出力したい場合のみ、'-a0'オプションを指定して下さい。
				//通常は、'-a1',又は,'-a2'を指定するか、デフォルトのまま('-a2')として下さい。
				//アルファ付きを指定しても、アルファ無しaviだったならば、sofdec2enc.exeが無視して、エラーにもならず安全です。
//}}2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int opt_v;			//コマンドを実行する前にコマンドライン文字列を表示し、コマンドを実行した後に終了ステータスを表示する。
int opt_n;			//コマンドライン文字列だけを表示して、コマンドを実行しない。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
const char* opt_o;				//出力ファイルのフルパス名。'-o'オプションが指定されなければ、'入力ファイル名.usm'とします。
const char* opt_p = SOFDEC2ENC_DEFAULTPATH;	//sofdec2enc.exeのパス名。デフォルトと異なる場所に有る場合は、'-p'オプションでsofdec2enc.exeのフルパス名を指定して下さい。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//\clip\tool\dpbmppp\dpbmppp.cのcmdline_whs()を元にして作成しました。
static void cmdline_whs(char* arg, int* p1, int* p2) {
	if(*p1 || *p2) { usage(); }			//'-w'が二回指定された,又は,'-h'が二回指定されたらエラー。
	*p1 = strtol(arg, &arg, 10);			//ピクセル数,又は,パーセンテージ,又は,分子を取得する。
	if(*p1 <= 0) { usage(); }			//数値の書式エラー,又は,0以下の値が指定されたらエラー。
	if(*arg) {					//数値の後に文字が有れば…
		switch(*arg) {
		case '%':				//パーセンテージ指定ならば…
			arg++;				//'%'の次へ進める。
			*p2 = 100;			//分母を100とする。
			break;
		case '/':				//分数指定ならば…
			arg++;				//'/'の次へ進める。
			*p2 = strtol(arg, &arg, 10);	//分母を取得する。
			if(*p2 <= 0) usage();		//数値の書式エラー,又は,0以下の値が指定されたらエラー。
			break;
		//default:
		//	//↓すぐ下でまとめてエラー扱い
		}
		if(*arg) { usage(); }			//'%',又は,分母の後に余分な文字が有ればエラー。
	}
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//{{2017/05/17追加:サフィックスを厳密に検査するようにしました。
//'C:\Home\Share\Piece\clip\tool\dTexDefC\winapp.c'のpass2()内の処理を元にして作成しました。
regexp* test_suffix(const char* path, const char* exp) {
	char *exp_exact, *fname, **suffixes, *suffix;
	regexp* prog;
	//指定された正規表現の式に、先頭の'^'と末尾の'$'を付与して、完全一致の式を作成する。
	if(str_has_prefix(exp, "^") || str_has_suffix(exp, "$")) { DIE(); }	//バグ。先頭の'^'と末尾の'$'は当関数が付与するので、呼び出し側で付与してはいけません。
	if(str_has_prefix(exp, "-")) { DIE(); }					//バグ。先頭の'-'も指定してはいけません。'-'で分割した個々のサフィックスに対して検査するので、'-'は正規表現のマッチ対象ではありません。
	exp_exact = strconcat("^", exp, "$", NULL);
	//正規表現オブジェクトを作成する。
	// - 個々のサフィックスの中に、唯一の一致するサフィックスが見つかった場合は、この正規表現オブジェクトが戻り値となります。
	prog = regcomp(exp_exact/*完全一致の式*/);
	if(!prog) { DIE(); }	//バグ。呼び出し側が指定した正規表現の式が不正です。
	//ファイル名を、'-'で分割する。
	strdup_splitpath(path, NULL, NULL, &fname, NULL);
	suffixes = strsplit(fname, "-", 0);
	//'-'で分割した個々の要素の内、二つ目から最後までをサフィックスと見なすので、最初の要素は飛ばす。
	if(*suffixes) { suffixes++; }	//有り得ないとは思うが万一空文字列だった場合のために、最初の要素が有る場合のみ進める。
	//個々のサフィックスについて…
	while((suffix = *suffixes++)) {
		//指定された正規表現に完全一致したら…
		if(regexec(prog, suffix)) {
			//残りのサフィックスの中に、同じ正規表現に完全一致するサフィックスが含まれていない事を確認するために、ダミーの正規表現オブジェクトを作成する。
			// - progをそのまま使って、残りのサフィックスを検査しないよう注意せよ。
			//   progをそのまま使うと、戻り値であるprogのstartp等が変わってしまう。
			regexp* prog_dummy = regcomp(exp_exact/*完全一致の式*/);
			if(!prog_dummy) { DIE(); }	//バグ。既に上でregcomp()が成功しているのだから、実際にはここで失敗する事は無いはずだが。
			//残りのサフィックスの中に、同じ正規表現に完全一致するサフィックスが含まれていない事を確認する
			while((suffix = *suffixes++)) {
				//指定された正規表現に完全一致したら…
				if(regexec(prog_dummy, suffix)) {
					error(EXIT_FAILURE, 0, "正規表現'%s'に一致するサフィックスが重複しています。(%s)", exp, path);
				}
			}
			//唯一の一致するサフィックスに完全一致した、正規表現オブジェクトを返す。
			// - 呼び出し側で、prog->startp等を参照して、一致したサフィックスを参照する事が出来ます。
			//   一致したサフィックスの文字列全体を参照したい場合は、返された正規表現オブジェクトの、prog->startp[0]～(prog->endp[0]-1)を参照して下さい。
			// - 別の案として、一致したサフィックスの文字列を返す方法も考えたのですが、(今の所有りませんが)正規表現内にキャプチャ式を指定した場合などに、
			//   正規表現そのものを返す方が目的の部分を取り出し易いだろうと考えて、サフィックスの文字列ではなく、正規表現オブジェクトを返す事にしました。
			return prog;
		}
	}
	//指定された正規表現に完全一致するサフィックスが無ければ、NULLを返す。
	return NULL;
}
//}}2017/05/17追加:サフィックスを厳密に検査するようにしました。
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int app_main(int argc, char* argv[]) {
	int exitCode = EXIT_SUCCESS;
	{
		char* endptr;
		int opt;
		opterr = 0; //オプションエラーは当プログラム内で処理するので、getopt()内でのエラー表示は不要。
		while((opt = getopt(argc, argv, "o:x:y:s:q:Q:a:p:vnh")) != -1) {	//コマンドラインオプションを処理する。
			switch(opt) {
			case 'o':
				{
					opt_o = optarg;
				}
				break;
			case 'x':
				{
					cmdline_whs(optarg, &opt_w1, &opt_w2);
				}
				break;
			case 'y':
				{
					cmdline_whs(optarg, &opt_h1, &opt_h2);
				}
				break;
			case 's':
				{
					cmdline_whs(optarg, &opt_w1, &opt_w2);
					cmdline_whs(optarg, &opt_h1, &opt_h2);
				}
				break;
//{{2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
//			case 'q':
//				{
////{{2017/05/16変更:'-q数値'オプションの定義を変更しました。
////					if(!strcmp(optarg, "0") ||	//-q0
////					   !strcmp(optarg, "1") ||	//-q1
////					   !strcmp(optarg, "2")) {	//-q2
////↓2017/05/16変更:'-q数値'オプションの定義を変更しました。
//					if(!strcmp(optarg, "0") ||	//-q0
//					   !strcmp(optarg, "1") ||	//-q1
//					   !strcmp(optarg, "2") ||	//-q2
//					   !strcmp(optarg, "3") ||	//-q3
//					   !strcmp(optarg, "4") ||	//-q4
//					   !strcmp(optarg, "5") ||	//-q5
//					   !strcmp(optarg, "6") ||	//-q6
//					   !strcmp(optarg, "7") ||	//-q7
//					   !strcmp(optarg, "8") ||	//-q8
//					   !strcmp(optarg, "9")) {	//-q9
////}}2017/05/16変更:'-q数値'オプションの定義を変更しました。
//						opt_q = TBL_q[*optarg - '0'];
//					} else {
//						//最低限のエラーチェックを行う。
//						while(isblank(*optarg)) { optarg++; }	//┬空白を除いた最初の文字が'-'で始まっていなければ、明らかにsofdec2enc.exeへの有効なオプションではない。
//						if(*optarg != '-') { usage(); }		//┘ただし、このエラーチェックを行っても、複数のオプションを指定した場合の二つ目以降のエラーは検出出来ないので、使用者が注意する事。
//						opt_q = optarg;		//-qオプション文字列
//					}
//				}
//				break;
//↓2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
			case 'q':
			case 'Q':
				{
					if(opt_q) { usage(); }	//'-q',又は,'-Q'オプションを複数回指定してはいけません。
					if(!strcmp(optarg, "0") ||	//-q0
					   !strcmp(optarg, "1") ||	//-q1
					   !strcmp(optarg, "2") ||	//-q2
					   !strcmp(optarg, "3") ||	//-q3
					   !strcmp(optarg, "4") ||	//-q4
					   !strcmp(optarg, "5") ||	//-q5
					   !strcmp(optarg, "6") ||	//-q6
					   !strcmp(optarg, "7") ||	//-q7
					   !strcmp(optarg, "8") ||	//-q8
					   !strcmp(optarg, "9")) {	//-q9
						opt_q = TBL_q[*optarg - '0'];
					} else {
						//最低限のエラーチェックを行う。
						while(isblank(*optarg)) { optarg++; }	//┬空白を除いた最初の文字が'-'で始まっていなければ、明らかにsofdec2enc.exeへの有効なオプションではない。
						if(*optarg != '-') { usage(); }		//┘ただし、このエラーチェックを行っても、複数のオプションを指定した場合の二つ目以降のエラーは検出出来ないので、使用者が注意する事。
						opt_q = optarg;		//-qオプション文字列
					}
					opt_Q = (opt == 'Q');	//'-q'ならばopt_Q=0、'-Q'ならばopt_Q=1とする。
				}
				break;
//}}2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
			case 'a':
				{
					opt_a = strtol(optarg, &endptr, 10);
//{{2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
//					if(*endptr || ((unsigned)opt_a > 1)) { usage(); }	//数値の書式エラー,又は,0～1の範囲外ならばエラー。
//↓2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
					if(*endptr || ((unsigned)opt_a > 2)) { usage(); }	//数値の書式エラー,又は,0～2の範囲外ならばエラー。
//}}2017/05/12変更:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
				}
				break;
			case 'p':
				{
					opt_p = optarg;
				}
				break;
			case 'v':
				{
					opt_v = 1;
				}
				break;
			case 'n':
				{
					opt_n = 1;
				}
				break;
			case 'h':
			default:
				usage();
			}
		}
	}
	if(optind >= argc) { usage(); }				//少なくとも一つの入力ファイルが指定されていなければいけない。
	if(opt_o && ((argc - optind) >= 2)) { usage(); }	//複数の一つの入力ファイルを指定した場合は、'-o'オプションを指定してはいけない。
	{
		//VFWを初期化する。
		AVIFileInit();
		//各aviファイルについて…
		while(optind < argc) {
			//aviファイルのストリーム情報を取得する。
			char*		pAviFileName = argv[optind];
			PAVIFILE	pAviFile;
			PAVISTREAM	pAviStream;
			AVISTREAMINFO	AviStreamInfo;
			HRESULT		hr;
			hr = AVIFileOpen(&pAviFile, pAviFileName, OF_READ|OF_SHARE_DENY_WRITE, NULL);
			if(hr) { error(EXIT_FAILURE, 0, "%s: AVIFileOpenが失敗しました。", pAviFileName); }
			hr = AVIFileGetStream(pAviFile, &pAviStream, streamtypeVIDEO, 0);
			if(hr) { error(EXIT_FAILURE, 0, "%s: AVIFileGetStreamが失敗しました。", pAviFileName); }
			hr = AVIStreamInfo(pAviStream, &AviStreamInfo, sizeof AviStreamInfo);
			if(hr) { error(EXIT_FAILURE, 0, "%s: AVIStreamInfoが失敗しました。", pAviFileName); }
			hr = AVIStreamRelease(pAviStream);
			if(hr) { error(EXIT_FAILURE, 0, "%s: AVIStreamReleaseが失敗しました。", pAviFileName); }
			hr = AVIFileRelease(pAviFile);
			if(hr) { error(EXIT_FAILURE, 0, "%s: AVIFileReleaseが失敗しました。", pAviFileName); }
			{
				GString* s = g_string_new(NULL);
				//コマンド名を指定する。
			//{{※要検討
			//不可	g_string_append_printf(s, "\"%s\"", opt_p);	//本当はこうしたいのだが、「ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。」というエラーになってしまった。
				g_string_append_printf(s, "%s", opt_p);		//仕方が無いのでこうした。もしコマンドのプルパス名の途中に空白文字が有ると、上手く動かないと思うが…
			//}}※要検討
				//入力ファイルを指定する。
				g_string_append_printf(s, " -video00=\"%s\"", pAviFileName);
//{{2017/07/19変更:サフィックス'-a0～2'を追加しました。
//				//'-a'オプションを反映する。
//				switch(opt_a) {
//				default:DIE();
//				case 0:	//アルファ無し
//					/** no job **/
//					break;
//				case 1:	//アルファ有り
//					g_string_append_printf(s, " -alpha00=\"%s\"", pAviFileName);	//'-alpha00=～'を指定しても、アルファ無しaviだったならば、sofdec2enc.exeが無視して、エラーにもならず安全です。
//					break;
////{{2017/05/12追加:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
//				case 2:	//サフィックスによって選択する
//	//{{2017/05/17変更:サフィックスを厳密に検査するようにしました。
//	//				//ファイル名の中に、'-add'が有るか?(もっと厳密に検査する方が望ましいのだが、実用上はこれでも充分だろう。)
//	//				if(strstr(pAviFileName, "-add")) {
//	//↓2017/05/17変更:サフィックスを厳密に検査するようにしました。
//					//ファイル名の中に、'-add'が有るか?
//					if(test_suffix(pAviFileName, "add")) {	//"-add"や"^add$"としないよう注意せよ。詳細はtest_suffix()関数内のコメントを参照して下さい。
//	//}}2017/05/17変更:サフィックスを厳密に検査するようにしました。
//						//入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする。
//						/** no job **/
//					} else {
//						//入力ファイル名がサフィックス'-add'を含んでなければ、アルファ付きaviならばアルファ付きでエンコードする。
//						g_string_append_printf(s, " -alpha00=\"%s\"", pAviFileName);	//'-alpha00=～'を指定しても、アルファ無しaviだったならば、sofdec2enc.exeが無視して、エラーにもならず安全です。
//					}
//					break;
////}}2017/05/12追加:入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする動作をデフォルトとしました。
//				}
//↓2017/07/19変更:サフィックス'-a0～2'を追加しました。
				{
					//入力ファイル名がサフィックス'-a0～2'を含んでいなかった場合のために、オプションによる指定値を取得しておく。
					int tmp_a = opt_a;
					//ファイル名の中に、'-a0'～'-a2'が有るか?
					regexp* prog = test_suffix(pAviFileName, "a([0-2])");	//"-a([0-2])"や"^a([0-2])$"としないよう注意せよ。詳細はtest_suffix()関数内のコメントを参照して下さい。
					if(prog) {
						//サフィックス'-a0～2'によるアルファ指定を、オプションによるアルファ指定よりも優先する。
						tmp_a = *prog->startp[1] - '0';
					}
					//アルファ指定を反映する。
					switch(tmp_a) {
					default:DIE();
					case 0:	//アルファ無し
						/** no job **/
						break;
					case 1:	//アルファ有り
						g_string_append_printf(s, " -alpha00=\"%s\"", pAviFileName);	//'-alpha00=～'を指定しても、アルファ無しaviだったならば、sofdec2enc.exeが無視して、エラーにもならず安全です。
						break;
					case 2:	//サフィックスによって選択する
						//ファイル名の中に、'-add'が有るか?
						if(test_suffix(pAviFileName, "add")) {	//"-add"や"^add$"としないよう注意せよ。詳細はtest_suffix()関数内のコメントを参照して下さい。
							//入力ファイル名がサフィックス'-add'を含んでいたら、アルファ付きaviでもアルファ無しでエンコードする。
							/** no job **/
						} else {
							//入力ファイル名がサフィックス'-add'を含んでなければ、アルファ付きaviならばアルファ付きでエンコードする。
							g_string_append_printf(s, " -alpha00=\"%s\"", pAviFileName);	//'-alpha00=～'を指定しても、アルファ無しaviだったならば、sofdec2enc.exeが無視して、エラーにもならず安全です。
						}
						break;
					}
				}
//}}2017/07/19変更:サフィックス'-a0～2'を追加しました。
				//出力ファイルを指定する。
				if(opt_o) {	//'-o'オプションが指定されていたら…
					g_string_append_printf(s, " -out=\"%s\"", opt_o);
				} else {	//'-o'オプションが指定されていなければ…
					char path[MAX_PATH], drive[MAX_DRIVE], dir[MAX_DIR], fname[MAX_FNAME];
					_splitpath(pAviFileName, drive, dir, fname, NULL);
					_makepath(path, drive, dir, fname, ".usm");
					g_string_append_printf(s, " -out=\"%s\"", path);
				}
				//サイズオプションが一つでも指定されていたら、ピクセル数を指定する。
				if((opt_w1 || opt_w2) || (opt_h1 || opt_h2)) {
					int w = AviStreamInfo.rcFrame.right - AviStreamInfo.rcFrame.left;
					int h = AviStreamInfo.rcFrame.bottom - AviStreamInfo.rcFrame.top;
					if(opt_w1) {
						if(opt_w2) {
							w = ((w * opt_w1) + (opt_w2 - 1)) / opt_w2;	//パーセンテージ指定,又は,分数指定の場合
						} else {
							w = opt_w1;	//ピクセル指定の場合
						}
					}
					if(opt_h1) {
						if(opt_h2) {
							h = ((h * opt_h1) + (opt_h2 - 1)) / opt_h2;	//パーセンテージ指定,又は,分数指定の場合
						} else {
							h = opt_h1;	//ピクセル指定の場合
						}
					}
					g_string_append_printf(s, " -scale=%d,%d", w, h);
//{{2016/12/30追加:入力ファイル名のサフィックスによる自動スケーリング指定に対応しました。
				//サイズオプションが一つも指定されていなければ…(明示的なサイズオプションと、サフィックスによる自動スケーリング指定の両方が指定されていた場合は、明示的なサイズオプションを優先する事にした。)
				} else {
	//{{2017/05/17変更:サフィックスを厳密に検査するようにしました。
	//			    //{{この範囲の判定処理は、DxlibHelper.cppのGetAutoScale()と同じにしました。DxlibHelper.cppのGetAutoScale()の判定処理と、当ツールの判定処理を、一致させておく必要が有ります。
	//				//ファイル名の中に、'-1x'～'-9x'が有るか?(もっと厳密に検査する方が望ましいのだが、実用上はこれでも充分だろう。)
	//				regexp* prog = regcomp("-([1-9])x");
	//				if(regexec(prog, pAviFileName)) {
	//			    //}}この範囲の判定処理は、DxlibHelper.cppのGetAutoScale()と同じにしました。DxlibHelper.cppのGetAutoScale()の判定処理と、当ツールの判定処理を、一致させておく必要が有ります。
	//↓2017/05/17変更:サフィックスを厳密に検査するようにしました。
					//ファイル名の中に、'-1x'～'-9x'が有るか?
					regexp* prog = test_suffix(pAviFileName, "([1-9])x");	//"-([1-9])x"や"^([1-9])x$"としないよう注意せよ。詳細はtest_suffix()関数内のコメントを参照して下さい。
					if(prog) {
	//}}2017/05/17変更:サフィックスを厳密に検査するようにしました。
						int AutoScale = *prog->startp[1] - '0';	//ファイル名の中に'-1x'～'-9x'が有れば、自動スケーリング値と見なす。
						int w = AviStreamInfo.rcFrame.right - AviStreamInfo.rcFrame.left;	//┐
						int h = AviStreamInfo.rcFrame.bottom - AviStreamInfo.rcFrame.top;	//│
						w = (w + (AutoScale - 1)) / AutoScale;					//├'-s1/1'～'-s1/9'が指定された場合と、同じ結果になります。
						h = (h + (AutoScale - 1)) / AutoScale;					//│
						g_string_append_printf(s, " -scale=%d,%d", w, h);			//┘
					}
//}}2016/12/30追加:入力ファイル名のサフィックスによる自動スケーリング指定に対応しました。
				}
//{{2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
//				//'-q'オプションを反映する。
//				if(*opt_q) {	//空文字でなければ…(空文字でも下記の処理を行っても害は無いのだが、無駄な空白の連続を避けるためにこの判定を行う事にした)
//					g_string_append_printf(s, " %s", opt_q);
//				}
//↓2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
				{
					const char* quality_string = "";	//ここに、品質指定文字列を取得する。品質指定文字列が指定されていなければ、""のままとなる。明示的に""が指定された場合と区別出来ないが、問題無い。
					//'-Q'オプションが指定されていたら…
					if(opt_Q) {
						//'-Q'オプションで指定された品質指定文字列を取得する。
						if(!opt_q) { DIE(); }	//(opt_Q!=0)かつ(opt_q==NULL)になる事は無いはずです。もしここで停止したら当ツールのバグです。
						quality_string = opt_q;
					//'-Q'オプションが指定されていなければ…
					} else {
	//{{2017/05/17変更:サフィックスを厳密に検査するようにしました。
	//					//ファイル名の中に、'-q数値'が有れば…(もっと厳密に検査する方が望ましいのだが、実用上はこれでも充分だろう。)
	//					regexp* prog = regcomp("-q([0-9])");
	//					if(regexec(prog, pAviFileName)) {
	//↓2017/05/17変更:サフィックスを厳密に検査するようにしました。
						//ファイル名の中に、'-q数値'が有れば…
						regexp* prog = test_suffix(pAviFileName, "q([0-9])");	//"-q([0-9])"や"^q([0-9])$"としないよう注意せよ。詳細はtest_suffix()関数内のコメントを参照して下さい。
						if(prog) {
	//}}2017/05/17変更:サフィックスを厳密に検査するようにしました。
							//サフィックス'-q数値'で指定された品質指定文字列を取得する。
							int Quality = *prog->startp[1] - '0';
							quality_string = TBL_q[Quality];
						//ファイル名の中に、'-q0'～'-q9'が無ければ…
						} else {
							//'-q'オプションが指定されていたら…
							if(opt_q) {
								//'-q'オプションで指定された品質指定文字列を取得する。
								quality_string = opt_q;
							}
						}
					}
					//品質指定文字列を反映する。
					if(*quality_string) {	//空文字でなければ…(空文字でも下記の処理を行っても害は無いのだが、無駄な空白の連続を避けるためにこの判定を行う事にした)
						g_string_append_printf(s, " %s", quality_string);
					}
				}
//}}2017/05/16変更:'-Q'オプションの追加,及び,サフィックス'-q数値'による品質指定に対応しました。
				//コマンドを実行する。
				// - \clip\tool\dpcc33\app.cのchildproc()を元にして作成しました。
				{
					FILE* fp;
					//'-v',又は,'-n'オプションが指定されていたら、コマンドライン文字列を表示する。
					if(opt_v || opt_n) {
						fprintf(stderr, "%s\n", s->str);
					}
					//'-n'オプションが指定されていなければ…
					if(!opt_n) {
						//パイプを作成してコマンドを実行する。
						fp = _popen(s->str, "r");
						if(!fp) { error(EXIT_FAILURE, 0, "%sを実行できません。", s->str); }
						//コマンドの標準出力を処理する。
						{
							char* glbuf = NULL;	//┬getline()用
							int   glcap = 0;	//┘
							while(getline(&glbuf, &glcap, fp) != EOF) {
								fputs(glbuf, stdout);
							}
							free(glbuf);	//getline()用バッファを開放する。
						}
						//パイプを閉じる。
						exitCode = _pclose(fp);
						//'-v'オプションが指定されていたら、終了ステータスを表示する。
						if(opt_v) {
							printf("Exitcode = %d\n", exitCode);
						}
					}
				}
				//コマンドラインの文字列を開放する。
				g_string_free(s, 1/*free_segment*/);
				//コマンドがエラー終了していたら、ループを抜ける。
				if(exitCode) { break; }
			}
			//次の入力ファイルへ進める。
			optind++;
		}
		//VFWを終了する。
		AVIFileExit();
	}
	return exitCode;
}
