vs2013多少位編譯器
『壹』 QT用VS還是MINGW編譯好,有什麼區別
都可以。
有時候會用到windows底下一些頭文件,這時候可以用VS編譯,如果用mingw編譯的話有時候會找不到這些頭文件。一般情況下用mingw就可以。
『貳』 怎麼編譯windows 64位版本的libav
libav是ffmpeg的一個分支,我純粹是出於喜歡avconv和avprobe這樣清晰的命名才對它有好感。
因為官方網站有一個編譯指南,以下只是本人在實際編譯過程中的一些問題點的記錄。
編譯環境准備
因為libav使用configure腳本來編譯,所以必須要安裝mingw的msys,這樣可以有一個bash來運行configure腳本,以及保證一個可用的gnu make來執行編譯。現在安裝Mingw可以使用mingw-get,類似於一個包管理器,我們只需要msys的包和coreutils的ext包就可以了。
其次我使用VS2013 Express版本的msvc來編譯。在之前版本的msvc,只需要安裝Windows SDK那個光碟鏡像就可以有一個命令行的編譯環境了,但是VS2013之後,必須安裝VS2013的光碟鏡像才可以(Express版本足矣)。
另外libav中有匯編代碼,語法是yasm,所以得下載一份windows版本的yasm。
依賴的第三方庫准備
我只准備了zlib和libfdk_aac兩個庫,前者其實我不知道libav哪裡用了,只是看到指南中有提及,就下載了,libfdk_aac據說是目前開源界最好的aac編解碼庫,只是因為用了一個custom的license,所以用它編譯出來的二進制文件是禁止發布的,所以想用支持這個庫的libav只能自己編譯用。
按照指南中的說明來修改編譯zlib即可,非常straight forward,只是要編譯一個x64的zlib.lib有需要注意的地方;cl.exe編譯object file的時候是沒有選項來指定要生成32位還是64位的,相反的,它用不同的cl.exe用來實現這一點,使用vs2013的兩個命令行快捷方式開啟編譯環境命令行即可(也就是給vcvarsall.bat傳遞不同的參數來打開相應的編譯環境命令行,例如我安裝的32位的VS2013 Express,就可以用vcvarsall.bat x86_amd64在PATH中准備好一個本身是32位的但生成的目標文件是64bit的cl.exe)。
libfdk_aac的代碼中沒有為msvc的toolchain來准備任何配置,所以我採用的最笨的方法:在VC中新建一個static library類型的工程,然後把需要的文件全部添加進來(除了aac decoder的部分),並且配置各種細節,來生成最後的64位的fdk-aac.lib文件。
configure libav
然後把zlib的頭文件和libfdk_aac的encoder的頭文件放到3rd/headers,把剛才生成的lib放到3rd/libs。正如指南中說的,msvc的toolchain會使用INCLUDE和LIB兩個環境變數來確定頭文件和庫文件的位置;在打開vcvarsall.bat之後,這兩個變數已經帶了系統庫的設定;而我們需要在./configure和make執行的時候,都要在這兩個變數中加上我們的3rd環境;因為用msys的bash來運行,只需要在這兩個命令前面如此設置即可:
INCLUDE=3rd/headers/;$INCLUDE LIB=3rd/libs/;$LIB ./configure
還有需要刪除mingw的link.exe,避免與msvc中的link.exe沖突,指南中也提到了。
另外附上我的configure參數,因為我的fdk-aac.lib中沒有解碼器,我專門聲明了不使用它的解碼器:
./configure --disable-debug \
--enable-gpl --enable-nonfree \
--enable-runtime-cpudetect \
--disable-avplay --disable-avserver \
--disable-encoder=aac \
--enable-libfdk-aac --disable-decoder=libfdk_aac \
--toolchain=msvc
libav本身的修改和make
libav在windows下,會把通過GetCommandLineW()來獲取UTF-16LE版本的命令行參數,並轉換成UTF-8之後才進行後續的所有操作(libav內部都是用UTF-8來統一對待字元串編碼的);但是在往控制台打log的時候,直接用fputs介面向stderr列印UTF-8的multibyte字元串,在CP_ACP(ANSI codepage)為gbk的中文windows上,字元串中的非ascii字元(例如剛才命令行傳入的中文文件名)就會列印為亂碼(因為系統用GBK來解碼UTF-8的字元串)。
解決方案是:
先用MultiByteToWideChar()把待列印的UTF-8 multibyte字元串轉換回UTF-16LE的wchar_t字元串;
這時候如果用fwputs來列印轉換後的字元串,會發現一遇到非ascii字元就會調用失敗(列印停止),這是因為默認的locale中的LC_TYPE(這個locale category專門控制字元相關的操作的)是"C",用setlocale(LC_TYPE, "")設置為系統默認(中文系統為GBK),或者顯式調用setlocale(LC_TYPE, ".936")設置為GBK,就能成功列印出UTF-16LE中的GBK能表示的字元;
但是這個locale+fwputs的方案只能顯示出一種ANSI方案支持的字元,想顯示出所有UTF-16LE支持的字元,應該直接使用windows的API調用,WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wcMsg, wcMsgLen, &wcMsgLen, NULL)。
以下是我對libavutil/log.c的patch:
--- log.c 2014-08-04 10:02:34 +0800
+++ libav-64bit/libav-10.3/libavutil/log.c 2014-09-10 06:42:02 +0800
@@ -59,6 +59,10 @@
static void colored_fputs(int level, const char *str)
{
+#if HAVE_COMMANDLINETOARGVW && defined(_WIN32)
+ int wcBufLen = 0;
+ wchar_t* wcBuf = NULL;
+#endif
if (use_color < 0) {
#if HAVE_SETCONSOLETEXTATTRIBUTE
CONSOLE_SCREEN_BUFFER_INFO con_info;
@@ -83,7 +87,19 @@
if (use_color) {
set_color(level);
}
+#if HAVE_COMMANDLINETOARGVW && defined(_WIN32)
+ wcBufLen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+ if (wcBufLen == 0) {
+ fputs("Failed to convert multibyte log string to widechar.\n", stderr);
+ exit(1);
+ }
+ wcBuf = (wchar_t*)malloc(wcBufLen *2);
+ wcBufLen = MultiByteToWideChar(CP_UTF8, 0, str, -1, wcBuf, wcBufLen);
+ WriteConsoleW(GetStdHandle(STD_ERROR_HANDLE), wcBuf, wcBufLen, &wcBufLen, NULL);
+ free((void*)wcBuf);
+#else
fputs(str, stderr);
+#endif
if (use_color) {
reset_color();
}
使用avconv的簡易教程
avprobe xxx.mkv
看清音軌是哪個,也就是一個數字音軌號;其實大部分時候一個容器中的所有音軌都是一種格式的,所以其實也不用看,下面用a指定所有的就好了
avconv -i xxx.mkv -c -c:1 libdfk_aac out.mkv
以上把1號軌按照aac重新編碼,別的軌全部對拷
avconv -i xxx.mkv -c -c:a libdfk_aac out.mkv
以上把所有音軌按照aac重新編碼,別的軌全部對拷
avconv -i xxx.mkv -i xxx.srt -c -c:a libdfk_aac out.mkv
以上演示另外附加一個srt,注意所有的-c參數都要放在所有-i文件之後
如何去掉輸入文件中的某些軌呢(需要借鑒avprobe xxx.mkv的輸出了):
avconv -i xxx.mkv -c -c:a libdfk_aac -map 0 out.mkv
以上語句實現功能跟不加-map 0一樣,map 0是說把第0號輸入文件中的所有軌都輸入到out.mkv
avconv -i xxx.mkv -c -c:a libdfk_aac -map 0:v out.mkv
以上語句講只輸出視頻軌
avconv -i xxx.mkv -c -c:a libdfk_aac -map 0:v -map 0:1 -map 0:s out.mkv
如果輸入文件中0為視頻,1和2均為音頻軌,3和4為字幕軌,以上語句可以只輸出0 1 3軌,不輸出2號音頻軌
avconv -i xxx.mkv -c -c:a libdfk_aac -map 0:0 -map 0:1 -map 0:3 -map 0:4 out.mkv
以上功能相同,只是完全用軌的數字序號來表示
avconv -i xxx.mkv -c -c:a libdfk_aac -map 0 -map -0:2 out.mkv
以上功能相同,只是用「負」來表示從之前形成的map中去掉指定的軌
注意map選項用在輸出之前,所有-i之後
某些文件(例如avi)在remux到mkv的時候會報錯,給avconv加上-fflags +genpts一般能解決