簡體   English   中英

使用DirectShow將視頻捕獲到AVI文件

[英]Capturing Video to an AVI File with DirectShow

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

附加代碼

// 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錯誤

有什么建議么?

謝謝

看一下這個話題 看來您錯過了一些步驟。

首先,您不會在任何地方使用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);

    // ...
}

其次,您使用的不是由圖形管理器管理的過濾器。 這里報價:

由pSource,pIntermediate和pSink指定的所有過濾器必須在調用該方法之前添加到圖形中。

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


如果上述步驟不能解決問題,則可以嘗試其他幾種方法。

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

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

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

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


如果您的代碼仍然無法正常工作,則應向我提供更多信息。 使用GraphEdit時是否實現了目標? 您的VDM電視卡過濾器的外觀(引腳,媒體類型)如何?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM