首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Directshow不能启动两次捕获

Directshow不能启动两次捕获
EN

Stack Overflow用户
提问于 2016-11-22 11:34:08
回答 2查看 221关注 0票数 0

我正试图按照windows中心上的DirectShow示例来开发自己的应用程序,该应用程序可以将屏幕和音频捕获到视频:将视频捕获到AVI文件

第一次捕获一切都没问题,但是在第二次什么都没发生,视频文件没有出现。有可能我忘了取消初始化了吗?

更新问题似乎不在于缺少发布。第二次流写入文件1.avi正在创建,但它是空的,当完成pMediaControl->Stop();时,它会自动删除

我第二次发现UPDATE2:

代码语言:javascript
运行
复制
                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.

返回E_INVALIDARG。因此,我添加了(使用这个):

代码语言:javascript
运行
复制
                if (a == 1) {
                    CComPtr<IPin> sourcePin;
                    CComPtr<IPin> dumpPin;
                    sourcePin = GetPin(pMux, PINDIR_OUTPUT);
                    dumpPin   = GetPin(pCap, PINDIR_INPUT);
                    hr = ppGraph->Connect(sourcePin, dumpPin);
                }

在第二次dumpPin值为NULL时,我发现了这个值,.The hr = ppGraph->AddFilter(pCap, L"Capture Filter");运行正常。我可以在哪里挖掘发现错误呢?

(代码已更新)

我的代码:

代码语言:javascript
运行
复制
#include "stdafx.h"
#include <iostream>

#include <windows.h>
#include <dshow.h>

#include <atlbase.h>
#include <dshow.h>


#include <vector>
#include <string> 

#pragma comment(lib, "strmiids")


IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir)
{
    BOOL       bFound = FALSE;
    IEnumPins  *pEnum;
    IPin       *pPin;

    pFilter->EnumPins(&pEnum);
    while (pEnum->Next(1, &pPin, 0) == S_OK)
    {
        PIN_DIRECTION PinDirThis;
        pPin->QueryDirection(&PinDirThis);
        if (bFound = (PinDir == PinDirThis))
            break;
        pPin->Release();
    }
    pEnum->Release();
    return (bFound ? pPin : 0);
}

HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
    // Create the System Device Enumerator.
    ICreateDevEnum *pDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));

    if (SUCCEEDED(hr))
    {
        // Create an enumerator for the category.
        hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
        if (hr == S_FALSE)
        {
            hr = VFW_E_NOT_FOUND;  // The category is empty. Treat as an error.
        }
        pDevEnum->Release();
    }
    return hr;
}

HRESULT InitCaptureGraphBuilder(
    IGraphBuilder **ppGraph,  // Receives the pointer.
    ICaptureGraphBuilder2 **ppBuild  // Receives the pointer.
)
{
    if (!ppGraph || !ppBuild)
    {
        return E_POINTER;
    }
    IGraphBuilder *pGraph = NULL;
    ICaptureGraphBuilder2 *pBuild = NULL;

    // Create the Capture Graph Builder.
    HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild);
    if (SUCCEEDED(hr))
    {
        // 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);

            // Return both interface pointers to the caller.
            *ppBuild = pBuild;
            *ppGraph = pGraph; // The caller must release both interfaces.
            return S_OK;
        }
        else
        {
            pBuild->Release();
        }
    }
    return hr; // Failed
}

struct Capture {
    IPropertyBag *pPropBag;
    IGraphBuilder *ppGraph;
    IBaseFilter *pCap;
    ICaptureGraphBuilder2 *pBuild;
};

void DisplayDeviceInformation(IEnumMoniker *pEnum,int a)
{
    IMoniker *pMoniker = NULL;
    std::vector<Capture> captures;

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

        VARIANT var;
        VariantInit(&var);

        hr = pPropBag->Read(L"DevicePath", &var, 0);
        if (SUCCEEDED(hr))
        {
            // The device path is not intended for display.
            printf("Device path: %S\n", var.bstrVal);
            VariantClear(&var);
        }

        IGraphBuilder *ppGraph;
        ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder
        hr = InitCaptureGraphBuilder(&ppGraph, &pBuild);


        IBaseFilter *pCap; // Video capture filter.
        hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
        if (SUCCEEDED(hr))
        {
            std::wstring name = std::wstring(L"C:\\a\\") + std::to_wstring(a) + std::wstring(L".avi");
            const wchar_t *cname = name.c_str();
            hr = ppGraph->AddFilter(pCap, L"Capture Filter");
            if (SUCCEEDED(hr)) {
                IBaseFilter *pMux;
                hr = pBuild->SetOutputFileName(
                    &MEDIASUBTYPE_Avi,  // Specifies AVI for the target file.
                    cname, // File name.
                    &pMux,              // Receives a pointer to the mux.
                    NULL);              // (Optional) Receives a pointer to the file sink.

                if (a == 1) {
                    CComPtr<IPin> sourcePin;
                    CComPtr<IPin> dumpPin;

                    sourcePin = GetPin(pMux, PINDIR_OUTPUT);
                    dumpPin   = GetPin(pCap, PINDIR_INPUT);

                    hr = ppGraph->Connect(sourcePin, dumpPin);

                }

                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(0);
                    pConfigMux->Release();
                }

                IConfigInterleaving *pInterleave = NULL;
                hr = pMux->QueryInterface(IID_IConfigInterleaving, (void**)&pInterleave);
                if (SUCCEEDED(hr))
                {
                    pInterleave->put_Mode(INTERLEAVE_CAPTURE);
                    pInterleave->Release();
                }
                pMux->Release();
            }
        }

        Capture capt;
        capt.ppGraph  = ppGraph;
        capt.pPropBag = pPropBag;
        capt.pCap = pCap;
        capt.pBuild = pBuild;
        captures.push_back(capt);

    }

    for (auto cap : captures)
    {
        IMediaControl* pMediaControl;
        cap.ppGraph->QueryInterface(&pMediaControl);
        pMediaControl->Run();
    }

    Sleep(5000);

    for (auto cap : captures)
    {
        IMediaControl* pMediaControl;
        cap.ppGraph->QueryInterface(&pMediaControl);
        pMediaControl->Stop();
        pMediaControl->Release();

        cap.pCap->Release();

        cap.ppGraph->Release();
        cap.pBuild->Release();

        cap.pPropBag->Release();
    }

    pMoniker->Release();
}

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    for (int a = 0; a <= 1; a++) {

        if (SUCCEEDED(hr))
        {
            IEnumMoniker *pEnum;

            hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
            if (SUCCEEDED(hr))
            {
                DisplayDeviceInformation(pEnum,a);
                pEnum->Release();
            }

        }
    }
    if (SUCCEEDED(hr))
    {
        CoUninitialize();
    }


    int i;
    std::cin >> i;
    return 0;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-12-03 09:45:10

我不知道如何太解决这个问题,所以我只是使用派生的外部进程。

票数 0
EN

Stack Overflow用户

发布于 2016-11-22 17:26:06

您可能需要在ppGraph函数结束时发布DisplayDeviceInformation、pBuild、pMediaControl和pCap,在循环结束时发布pMux。最好使用一些智能指针来代替。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40740785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档