天天看點

用Visual Studio 2019生成FFmpeg解決方案(四)

作者:編譯小王子
前情提要:隻怪自己水準有限、知識面還是太窄,上篇編譯時碰到了彙編,知識儲備明顯不夠,這才真是書到用時方恨少,經過惡補,大體上一知半解了,繼續啃骨頭,在行動中學習,學習中記錄,開幹!

一、編譯環境補充

由于涉及彙編的編譯,是以需要在Visual Studio環境中增加編譯支援。

1、nasm下載下傳

官方下載下傳位址在這裡:NASM

下載下傳下來的話隻有nasm.exe,如果想要內建到Visual Studio環境中,還需要下載下傳相應的nasm.props、nasm.xml和nasm.targets三個檔案。

2、nasm.exe配置

nasm.exe需要配置到環境變量中,建立環境變量NASMPATH,然後指定到nasm.exe所在目錄。還有一種方法是将nasm.exe拷貝到Visual Studio安裝目錄中,即VCInstallDir宏定義所指向的目錄,例如我使用Visual Studio 2019的目錄位置:

用Visual Studio 2019生成FFmpeg解決方案(四)

這樣Visual Studio就可以找到nasm.exe了。

3、內建Visual Studio

将nasm.props、nasm.xml和nasm.targets拷貝到Visual Studio指定目錄,不同版本有一定差别,整理了一下不同版本的位址,請對号入座

1. Visual Studio 2013: C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\BuildCustomizations
 2. Visual Studio 2015: C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\BuildCustomizations
 3. Visual Studio 2017: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\BuildCustomizations
 4. Visual Studio 2019: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Microsoft\VC\v160\BuildCustomizations           

完成之後,重新開機下VS,通過右鍵單機項目-> 生成依賴項->生成自定義,如果能找到nasm的選項,說明配置成功。

用Visual Studio 2019生成FFmpeg解決方案(四)

至此,我們的Visual Studio就支援nasm來編譯彙編了。

二、FFmpeg項目目錄結構調整

由于這個項目的目錄結構比較複雜(C和彙編語言都有相應的引用依賴,之前的目錄結構有點别扭),加上考慮盡可能不動原有源碼目錄結構的前提下,将目錄結構調整如下:

用Visual Studio 2019生成FFmpeg解決方案(四)

說明:維持原有FFmpeg的源碼目錄結構不動,在該目錄下建立一個msvc目錄,用于存放VS工程以及動态生成的檔案。在VS工程中将源碼引用進來進行編譯,具體VS項目結構如下圖所示:

用Visual Studio 2019生成FFmpeg解決方案(四)

通過篩選器來組織源碼,這樣開起來也比較舒服,相應的變更一下include就可以了。

三、nasm編譯設定

前面已經配置好了nasm環境,但實際生成項目後并沒有看到有什麼變化。我就先學現賣:

首先把需要編譯的asm檔案當做源碼導入工程,這裡是放在x86篩選器下面;

然後右鍵點選asm檔案(最好是把所有asm檔案都選中之後再右鍵,否則得一個個設定很麻煩)檢視屬性

在屬性頁中會看到項類型自動被設定為不參與生成,将其改為Netwide Assembler,然後确定,這時就會出現nasm的配置頁面:

用Visual Studio 2019生成FFmpeg解決方案(四)

按你實際的代碼結構配置好相應的目錄,就可以開始編譯了。好了,回到主線任務!!!

四、編譯libavutil項目

前面配置好之後,啟動編譯就會發現asm檔案最開始會被編譯:

用Visual Studio 2019生成FFmpeg解決方案(四)

莫名有點興奮,奇怪的知識又增加了,然而問題還是要一個個解決的。

問題10:error C2065: “__asm__”: 未聲明的辨別符

重新回到問題10,通過回頭看,感覺直接修改源碼貌似不妥當:

用Visual Studio 2019生成FFmpeg解決方案(四)

在上面源碼中可以看到,是否編譯内聯彙編,是通過HAVE_MMX_INLINE來控制的,既然是通過宏控制,那麼就是說内聯彙編可以參與也可以不參與,而這個宏定義是config.h(由configure生成)來定義的,隻要把這個宏定義設為0,就表明不參與内聯彙編了。是以可能更好的辦法是修改config.h,是以将config.h中涉及内聯彙編的位置都改成0,主要是HAVE_MMX_INLINE和HAVE_INLINE_ASM兩個。

經過修改之後,問題10和前面的問題11就沒再出現了。

問題12:error : unknown CPU type or flag 'amdnop'

這個是在asm編譯的時候出現的,這個一開始我也沒有頭緒,因為我的彙編基礎連入門都算不上,但是我發現編譯彙編的時候引用了config.asm,這個和config.h是起到相同作用的,隻是一個是給asm用的,一個是給C用的。通過搜尋config.asm,發現有個叫HAVE_CPUNOP的宏定義,該值為1,改成0說不定就好了。果然,錯誤解決(但不知道有沒有什麼後遺症,哈哈,先管不了這麼多了)。 相應的把config.h的宏定義也改為0。

問題13:fatal error C1083: 無法打開包括檔案: “drm.h”: No such file or directory

這個頭檔案在整個源碼中是找不到的,這個應該是Linux下libdrm庫提供的,而這個庫目前沒有找到在Windows下的支援。源碼在這裡:Mesa / drm · GitLab。

該錯誤出現在hwcontext_drm.c,我暫時将其從項目中移除(注意:不是删除),不參與項目編譯。這個錯誤在編譯期間就不存在了,如果在連結時有問題我們再來解決吧。

類似的:排除了hwcontext_mediacodec.c、hwcontext_videotoolbox.c、hwcontext_cuda.c、hwcontext_opencl.c、hwcontext_vulkan.c、hwcontext_vdpau.c、hwcontext_qsv.c、hwcontext_vaapi.c、vulkan.c

問題14:error C2143: 文法錯誤: 缺少“)”(在“常數”的前面)

這個問題出現在tx_template.c,出錯位置為:

用Visual Studio 2019生成FFmpeg解決方案(四)

但SR_POW2_TABLES以及後續的TX_MAX_SUB 都是有定義的,為什麼會出錯呢?跟蹤了下源碼,發現還關聯了tx_priv.h和tx_double.c,tx_priv.h 中很多結構依賴的宏定義在tx_double.c中定義了,例如TX_DOUBLE,而tx_double.c 代碼中就隻有三行:

#define TX_DOUBLE
#include "tx_priv.h"
#include "tx_template.c" 
           

在項目中搜尋了下tx_template.c檔案,發現它是被當做頭檔案來引用的:

用Visual Studio 2019生成FFmpeg解決方案(四)

是以是不是說tx_template.c壓根就不需要參與編譯?将該檔案從項目中排除,編譯沒有錯誤,同問題13相同,編譯不出差,可能會在連結時出錯,暫且如此,等連結出錯了再說。

問題14:warning C4013: “gmtime_r”未定義;假設外部傳回 int

雖然是個warning,但是間接導緻了error C2100: 非法的間接尋址的錯誤:

用Visual Studio 2019生成FFmpeg解決方案(四)

gmtime_r是linux提供的接口,用于将月曆時間timep轉換為用UTC時間表示的時間,并将其存儲到使用者提供的結構體當中。通過代碼追蹤,是在time_internal.h對該函數進行了處理:

用Visual Studio 2019生成FFmpeg解決方案(四)

可以看出和HAVE_GMTIME_R這個宏有關,我們不急于更改代碼,還是将該宏由1改為0。類似的,也将HAVE_LOCALTIME_R改為0。

OK!編譯過程不再有錯誤了,但還存在84個連結錯誤!

用Visual Studio 2019生成FFmpeg解決方案(四)

曙光已現,預知後事如何,且聽下回分解。

繼續閱讀