如何使用DirectShow编写avi文件

时间:2013-01-24 15:35:54

标签: c++ winapi video directshow

我正在尝试根据我的Decklink SDI卡的流媒体来编写一个avi视频文件,在查看互联网后,我在这里写了这个代码我的问题是该程序没有写这里的文件代码:

#include <Windows.h>
#include <DShow.h>
#include <iostream>


 int main(void)
{
IGraphBuilder* pGraph = NULL;
ICaptureGraphBuilder2* pBuild = NULL;
IMediaControl* pControl = NULL;

ICreateDevEnum* pDevEnum = NULL;
IEnumMoniker* pEnum = NULL;
IMoniker *pMoniker = NULL;
IMoniker* goodMoniker = NULL;
IBaseFilter* pCap;
HRESULT hr;

//Initialize pGraph
hr = CoInitialize(NULL);
   hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **) &pGraph);
if(FAILED(hr))
{
    printf("ERROR - Could not initialize COM library");
    return 1;
}

//Initialize pBuild


 hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**) &pBuild);
if(FAILED(hr))
{
    printf("ERROR - Could not create the Filter Graph Manager.");
    return 2;
}
pBuild->SetFiltergraph(pGraph);



hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pDevEnum));
if(SUCCEEDED(hr))
{
    hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
}


HWND hList;

while(pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
    IPropertyBag* pPropBag;
    hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
    if(FAILED(hr))
    {
        pMoniker->Release();
        continue;
    }

    VARIANT varName;
    VariantInit(&varName);
    hr = pPropBag->Read(L"Description", &varName, 0);
    if(FAILED(hr))
    {
        hr = pPropBag->Read(L"FriendlyName", &varName, 0);
    }
    if(SUCCEEDED(hr))
    {
        for(int i=0;i<20;i++)
        {
           std::cout<<(char)*(varName.bstrVal + i);
        }

        char yn;
        std::cin>>yn;

        if(yn=='Y')
        {
            std::cout<<"SUCCESSFUL"<<std::endl;
            goodMoniker = pMoniker;
            VariantClear(&varName);
        }
    }
    pPropBag->Release();
    if(pMoniker != goodMoniker)
    {
        pMoniker->Release();
    }
}


hr = goodMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)(&pCap));

if(SUCCEEDED(hr))
{
    hr = pGraph->AddFilter(pCap, L"Capture Filter");

}

IBaseFilter *pMux = NULL;

//  hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);

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

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.  


hr = pCap->QueryInterface(IID_IMediaControl,(void**) pControl);

printf("START ");
hr = pControl->Run();

Sleep(100000);
hr = pControl->Stop();
CoUninitialize();


pGraph->Release();
pBuild->Release();
pCap->Release();

}

这是我在尝试debbug时得到的错误消息:

  Unhandled exception at 0x776015de in STREAMMMMM.exe: 0xC0000005: Access violation reading location 0x00000000.

程序崩溃了这一行:

 r = pCap->QueryInterface(IID_IMediaControl,(void**) pControl);

1 个答案:

答案 0 :(得分:3)

关于如何使用DirectShow在Internet上写入AVI,有几十个(如果不是数百个)示例。

这个特定的代码片段甚至没有开始写。它只准备管道,你甚至没有做IMediaControl::Run,你应该做什么。此外,您应该等到写得足够多,然后停止录制,然后才释放接口指针。

看一下这个Q:Using a DirectShow filter without registering it, via a private CoCreateInstance,了解您开始实际捕获和编写时所缺少的内容(特别是IMediaControl::RunSleep)。