Как записать avi файл с DirectShow

Я пытаюсь написать avi-видеофайл на основе потоковой передачи моей карты Decklink SDI, посмотрев в Интернете, и здесь я написал этот код, моя проблема в том, что программа не записывает файл, вот код:

#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();

}

вот сообщение об ошибке, которое я получаю, когда пытаюсь его отладить:

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

программа вылетает в этой строке:

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

person Engine    schedule 24.01.2013    source источник
comment
Не записывайте файлы в корневой каталог c:\, UAC запрещает доступ на запись. Используйте образец AmCap для вдохновения. msdn.microsoft.com/en-us/ библиотека/dd373424%28v=VS.85%29.aspx   -  person Hans Passant    schedule 24.01.2013


Ответы (1)


Примеров записи в AVI с DirectShow в Интернете десятки, если не сотни.

Этот конкретный фрагмент кода даже не начинает писаться. Он только подготавливает пайплайн, а вы даже не делаете IMediaControl::Run того, что должны делать. Далее следует подождать, пока вы напишете достаточно, а затем остановить запись и только после этого отпустить указатели интерфейса.

Взгляните на этот вопрос: Использование DirectShow отфильтруйте без регистрации через частный CoCreateInstance то, чего вам не хватает, чтобы начать фактический захват и запись (в частности, IMediaControl::Run и Sleep).

person Roman R.    schedule 24.01.2013
comment
Я просто хочу записать 10 секунд с моего устройства - person Engine; 24.01.2013
comment
Я добавил ссылку на другой вопрос, чтобы вы могли посмотреть. - person Roman R.; 24.01.2013
comment
@ Роман, спасибо за вашу помощь, я отредактировал код на основе другого вопроса, но он все еще не работает (пожалуйста, посмотрите мой отредактированный вопрос - person Engine; 25.01.2013
comment
Вы должны выполнить некоторую отладку и получить коды ошибок. Возможно, вы также захотите взглянуть на SDK от Blackmagic. Он общедоступен и содержит примеры кода для проектов DirectShow, см. \Blackmagic DeckLink SDK 9.5\Win\Samples там. Также есть готовые исполняемые файлы. Помимо уже упомянутых, могут быть и другие причины, по которым видео не может быть записано, например, установка неправильного формата захвата на плате Decklink. - person Roman R.; 25.01.2013
comment
Мой код не работает ни с веб-камерой, ни с SDI-картой Decklink. - person Engine; 25.01.2013
comment
и пример Blackmagic слишком сложен для понимания (по крайней мере для меня), и они используют кодеки, и все, что я хочу, это получить видео, записывая его. еще раз спасибо за помощь - person Engine; 25.01.2013
comment
Я не думаю, что вы указали правильную строку отказа, но в этой строке определенно есть проблема. Должно было быть так: pGraph->QueryInterface(..., IID_IMediaControl, то есть pGraph, а не pCap. - person Roman R.; 25.01.2013
comment
Я сделал, но я изменил свой код, я просто не понимаю, почему так сложно захватить видео с помощью Direchtshow. Я сделал это с opencv, и все было в порядке, качество - моя проблема. - person Engine; 25.01.2013