2012-12-06 95 views
2

我正在嘗試用directshow編寫C++應用程序,將視頻捕獲保存到文件。 代碼的步驟是: 1.創建捕獲圖形生成器 2.創建系統設備枚舉 3.創建系統設備枚舉 - 爲了獲取捕捉過濾 4.創建視頻採集類的枚舉 5.創建查詢捕獲視頻使用DirectShow捕獲視頻到AVI文件

附加代碼

// gets the device filter 
HRESULT getDeviceFilter(REFCLSID clsid, int order, IBaseFilter **pCap) 
{ 

ICreateDevEnum *pDevEnum = NULL; 
IEnumMoniker *pEnum = NULL; 

// Create the System Device Enumerator. 
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 
           CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, 
           reinterpret_cast<void**>(&pDevEnum)); 

if (SUCCEEDED(hr)) 
{ 
    // Create an enumerator for the video capture category. 
    hr = pDevEnum->CreateClassEnumerator(clsid, &pEnum, 0); 
} 

IMoniker *pMoniker = NULL; 

if (pEnum->Next(1, &pMoniker, NULL) == S_OK) 
    hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)pCap); 

return hr; 
} 


int main() 
{ 
IGraphBuilder *pGraph = 0; 
ICaptureGraphBuilder2 *pBuild = 0; 
IBaseFilter *pCap = 0; 
HRESULT hr = CoInitialize(NULL); 

// Create the Capture Graph Builder. 
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, 
           NULL, 
           CLSCTX_INPROC_SERVER, 
            IID_ICaptureGraphBuilder2, 
           (void**)&pBuild); 


ICreateDevEnum *pDevEnum = NULL; 
IEnumMoniker *pEnum = NULL; 

// Create the System Device Enumerator. 
hr = CoCreateInstance(CLSID_SystemDeviceEnum, 
         NULL, 
         CLSCTX_INPROC_SERVER, 
         IID_ICreateDevEnum, 
         reinterpret_cast<void**>(&pDevEnum)); 



IBaseFilter *pMux = 0; 
hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi, // Specifies AVI for the target file. 
           L"C:\\Example.avi", // File name. 
           &pMux,    //  Receives a pointer to the mux. 
           NULL);    //  (Optional) Receives a pointer to the file sink. 


// gets the first device, VDM tv card 
hr = getDeviceFilter(CLSID_VideoInputDeviceCategory, 0, &pCap); 


hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, // Pin category. 
          &MEDIATYPE_Video,  // Media type. 
          pCap,     // Capture filter. 
          NULL,     // Intermediate filter (optional). 
          pMux);     // Mux or file sink filter. 

// Release the mux filter. 
pMux->Release(); 

IConfigAviMux *pConfigMux = NULL; 
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux); 
if (SUCCEEDED(hr)) 
{ 
    pConfigMux->SetMasterStream(1); 
    pConfigMux->Release(); 
} 

return 0; 
} 

然而,在調用RenderStream我得到一個E_INVALIDARG錯誤

有什麼建議嗎?

感謝

+0

您是否在我的答案中嘗試過這些建議? –

回答

1

看看this topic。看來你已經錯過了一些步驟。

首先,你沒有在任何地方使用pGraph。您應該創建圖形管理器,然後通過使用SetFilterGraph向圖形管理器提供一個指針來初始化圖形構建器。

// Create the Filter Graph Manager. 
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER, 
    IID_IGraphBuilder, (void**)&pGraph); 
if (SUCCEEDED(hr)) 
{ 
    // Initialize the Capture Graph Builder. 
    pBuild->SetFiltergraph(pGraph); 

    // ... 
} 

其次,您使用的是不受圖管理器管理的過濾器。從here引述:

所有通過的PSource,pIntermediate指定的過濾器,和pSink必須被添加到圖形調用方法之前進行。

您必須將過濾器pCappMux添加到先前創建的圖表管理器,使用AddFilter。您應該在調用RenderStream之前執行此操作。這是因爲RenderStream最終調用管理器上的連接方法。


如果上述步驟不能解決您的問題,還有其他幾件事您可以嘗試。

設備過濾器。您正在使用CLSID_VideoInputDeviceCategory的第一個設備,但是您確定這是正確的設備嗎?網絡攝像機等也包含在這個類別中。確保沒有連接相同類別的其他設備,然後重試。

連接。每個設備都不同。這可能是因爲您的設備無法直接連接到多路複用器。在這種情況下,我們必須找出原因並確定是否需要連接其他濾波器(如解碼器)。 GraphEdit是找到這些過濾器的非常快速的方法。

針類別/媒體類型。根據我的經驗,E_INVALIDARG是由RenderStream的前兩個參數引起的時間的90%。嘗試將引腳類別或媒體類型設置爲NULL

系統設備枚舉器:正如您自己描述的那樣,您正在創建一個系統設備枚舉器兩次。對我來說,這似乎很奇怪,爲什麼不使用一個呢?


如果你的代碼仍然無效,你應該提供給我更多的信息。在使用GraphEdit時你有沒有達到目標? VDM電視卡過濾器的外觀如何(引腳,媒體類型)?

相關問題