DirectShow SDK編譯中易出現的問題
由於需要進行視訊採集,昨天開始搜尋資料,發現現在流行的是DirectShow來進行開發,昨天下載安裝了個DirectX 9.0 SDK,於是痛苦的配置旅程開始了。現在我們來重溫一下這個痛苦的歷程吧。先介紹下我的配置吧:
Microsoft DirectX 9.0 SDK + Microsoft Visual Stiduo 2005
我的Microsoft DirectX 9.0 SDK 安裝在D盤根目錄,進入這個目錄D:\DXSDK\Samples\C++\DirectShow\Capture裡面有幾個專案檔案,我們拿AMCap這個專案來用,首先我們拷貝一個副本AMCap1(為了保險起見!),要想看看AMCap最終的執行效果,我們可以進入這個目錄:D:\DXSDK\Samples\C++\DirectShow\Bin
用Microsoft Visual Stiduo 2005開啟工程,可能需要轉換下,轉換就是了,先什麼也別做,開始編譯工程(預設的配置管理器中的活動解決方案配置為Debug Unicode,活動解決方案平臺是Win32),我得到了下面的錯誤:
amcap.cpp
C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(222) : error C2146: syntax error : missing ';' before identifier 'PVOID64'
C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C2146: syntax error : missing ';' before identifier 'Buffer'
C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\include\winnt.h(5940) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
d:\DXSDK\include\uuids.h : warning C4819: The file contains a character that cannot be represented in the current code page (936). Save the file in Unicode format to prevent data loss
typedef void * POINTER_64 PVOID64; 修改為
#define POINTER_64 __ptr64 //加上這一行
typedef void*PVOID;
typedef void* POINTER_64 PVOID64;
對於第二個錯誤改成:int i 就可以了。
修改完錯誤繼續編譯,發現編譯已經沒有錯誤了,只有一些警告,可以不去管它,但是有這樣的一個錯誤:
LINK : fatal error LNK1104: 無法開啟檔案“..\..\baseclasses\debug_unicode\strmbasd.lib”
看錯誤的意思是缺少了一個庫檔案,於是在網上找了一下,原來需要先編譯baseclasses,開啟你的dx的sdk安裝目錄,本例為:D:\DX90SDK\Samples\C++\DirectShow\
這裡就有一個叫baseclasses的工程,為安全起見,請先備份此工程,然後開啟該工程。轉換後開始編譯,我們收到了下面的錯誤:
.\wxdebug.cpp(567) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
.\winutil.cpp(2104) : error C2065: 'Count' : undeclared identifier
.\winutil.cpp(2106) : error C2228: left of '.peRed' must have class/struct/union
.\winutil.cpp(2106) : error C2228: left of '.peRed' must have class/struct/union
.\winutil.cpp(2107) : error C2228: left of '.peGreen' must have class/struct/union
.\winutil.cpp(2107) : error C2228: left of '.peGreen' must have class/struct/union
.\winutil.cpp(2108) : error C2228: left of '.peBlue' must have class/struct/union
.\winutil.cpp(2108) : error C2228: left of '.peBlue' must have class/struct/union
.\winutil.cpp(2124) : error C2228: left of '.peFlags' must have class/struct/union
.\outputq.cpp(664) : error C2065: 'iDone' : undeclared identifier
對於前一個錯誤
//將static g_dwLastRefresh =0;
//修改為intstatic g_dwLastRefresh =0;
第三個錯誤,在出錯的檔案中會看到下面的程式碼,修改辦法一併在下面列出,註釋裡有說明。
LONG iLost = 0;
LONG iDone = 0; //這是我們修改的地方,加入這一行程式碼
for (long iDone = 0;
iDone < nSamples || (m_nBatched != 0 && m_bSendAnyway);
) {
//pragma message (REMIND("Implement threshold scheme")) ASSERT(m_nBatched < m_lBatchSize);
if (iDone < nSamples) {
m_ppSamples[m_nBatched++] = ppSamples[iDone++];
}
if (m_nBatched == m_lBatchSize ||
nSamples == 0 && (m_bSendAnyway || !m_bBatchExact)) {
LONG nDone;
DbgLog((LOG_TRACE, 4, TEXT("Batching %d samples"),
m_nBatched));
if (m_hr == S_OK) {
m_hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
m_nBatched,
&nDone);
} else {
nDone = 0;
}
iLost += m_nBatched - nDone;
for (LONG i = 0; i < m_nBatched; i++) {
m_ppSamples[i]->Release();
}
m_nBatched = 0;
}
}
*nSamplesProcessed = iDone - iLost; //這是編譯報錯誤的地方
現在我們來得到其他三個庫檔案,開啟配置管理器,我們上面的配置是這樣的:
活動解決方案配置為Debug Unicode,活動解決方案平臺是Win32
分別修改如下的三種模式分別編譯:
活動解決方案配置為Debug,活動解決方案平臺是Win32
活動解決方案配置為Release Unicode,活動解決方案平臺是Win32
活動解決方案配置為Release,活動解決方案平臺是Win32
這樣我們就得到了4個庫檔案。
D:\DXSDK\Samples\C++\DirectShow\BaseClasses\Debug下有了一個庫檔案strmbasd.lib
D:\DXSDK\Samples\C++\DirectShow\BaseClasses\Debug_Unicode下有了一個庫檔案strmbasd.lib
D:\DXSDK\Samples\C++\DirectShow\BaseClasses\Release下有了一個庫檔案STRMBASE.lib
D:\DXSDK\Samples\C++\DirectShow\BaseClasses\Release_Unicode下有了一個庫檔案STRMBASE.lib
現在大家再看看上面的那個紅色的連結錯誤,知道怎麼回事了吧。
好了,我們現在回去編譯AMCap這個工程吧,怎麼樣,搞定了吧!
附1:
POINTER_64是一個巨集,在64位編譯下起作用,它包含在SDK目錄下的BASETSD.H中(Microsoft Visual Studio 8\VC\PlatformSDK\Include\basetsd.h(23):#define POINTER_64 __ptr64),但DXSDK自己也帶了一個basetsd.h,裡面沒有定義POINTER_64,從而導致出錯。
方法1:
在Tools -> Options -> Projects and Solutions -> VC++ Directories -> Include Files裡確保系統包含目錄(以$打頭的)在最前面,同時在 project properties下面的“C/C++ -> General”中確保“Additional Include Directories”為空(因為它會被優先編譯,這樣就輪不到VC\PlatformSDK\Include\basetsd.h),所有的包含目錄都應該在上面的include裡面。這種方法不用改程式碼。
方法2:
在DXSDK自己的basetsd.h裡自己定義#define POINTER_64 __ptr64
附2:
開啟project->BaseClasses properties->configuration->C/C++ ->Command Line,增加/wd4430選項
附3:
C++標準語法的問題,因為在之前在for迴圈內定義的變數可以在for之外的地方使用,即在第一個for裡for(int i,...),以後的for再使用i不必再宣告,解決方法也很簡單,開啟project->BaseClasses properties->configuration->C/C++->Language->Force Comformance in For Loop Scrope設定為No即可。
相關資料: