浪迹在C-Model和与RTL之间
Graphics&Multimedia

  CoInitialize(NULL);

    HRESULT hr;
    IGraphBuilder* pGraphBuilder=NULL;
    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&pGraphBuilder);

    IBaseFilter*    pMpeg4PSFileStream;
    IBaseFilter*    pMpegDemuxFilter;
    IBaseFilter*    pMpeg4VideoDecoder;
    IBaseFilter*    pOverlayMaxer2;
    IBaseFilter*    pVideoRenderer;
    
    hr=CoCreateInstance(CLSID_Mpeg4PSFileStream, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMpeg4PSFileStream);
    if (FAILED(hr))
      AfxMessageBox("err create CLSID_Mpeg4PSFileStream");

    hr=CoCreateInstance(CLSID_MpegDemuxFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMpegDemuxFilter);
    if (FAILED(hr))
      AfxMessageBox("err create CLSID_MpegDemuxFilter");

    hr=CoCreateInstance(CLSID_Mpeg4VideoDecoder, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pMpeg4VideoDecoder);
    if (FAILED(hr))
      AfxMessageBox("err create CLSID_Mpeg4VideoDecoder");

    hr=CoCreateInstance(CLSID_OverlayMaxer2, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pOverlayMaxer2);
    if (FAILED(hr))
      AfxMessageBox("err create CLSID_OverlayMaxer2");

    hr=CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideoRenderer);
    if (FAILED(hr))
      AfxMessageBox("err create CLSID_VideoRenderer");

    pGraphBuilder->AddFilter(pMpeg4PSFileStream    , NULL);
    pGraphBuilder->AddFilter(pMpegDemuxFilter    , NULL);
    pGraphBuilder->AddFilter(pMpeg4VideoDecoder , NULL);
    pGraphBuilder->AddFilter(pOverlayMaxer2     , NULL);
    pGraphBuilder->AddFilter(pVideoRenderer     , NULL);

    //set the source file
    IFileSourceFilter * pLoader;
    pMpeg4PSFileStream->QueryInterface(IID_IFileSourceFilter, (void **)&pLoader);

    hr=pLoader->Load(L"E:\\temp\\mpeg4_ps.mpg",NULL);
    if (FAILED(hr))
      AfxMessageBox("装载文件出错!");

    //connect filter
    char *strPinName = new char;
    IEnumPins*    EnumPins;
    IPin*        OutPin;
    IPin*        InPin;
    ULONG        fetched;
    PIN_INFO    pinfo;
    
    
    // find source output
    pMpeg4PSFileStream->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);    // only 1 pin for source, so we know this is the one we need
    EnumPins->Release();

    // find Demux Filter input
    pMpegDemuxFilter->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);
    InPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();        // make sure you release the returned IBaseFilter interface
    while (pinfo.dir == PINDIR_OUTPUT)        // check if we have wrong pin (not input pin),2 output pin
    {
        InPin->Release();
        EnumPins->Next(1, &InPin, &fetched);        // if so, get next pin
        InPin->QueryPinInfo(&pinfo);
        pinfo.pFilter->Release();
    }

    // connect -- 1
    pGraphBuilder->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();

    // find Demux Filter output
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();
    if (pinfo.dir == PINDIR_INPUT)        // check if we have wrong pin (not input pin),only 1 input pin
    {
        InPin->Release();
        EnumPins->Next(1, &OutPin, &fetched);        // if so, get next pin
    }
    EnumPins->Release();

    // find Vweb Mpeg4 Video Decoder input
    pMpeg4VideoDecoder->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);
    InPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();        // make sure you release the returned IBaseFilter interface
    if (pinfo.dir == PINDIR_OUTPUT)        // check if we have wrong pin (not input pin),only 1 input pin
    {
        InPin->Release();
        EnumPins->Next(1, &InPin, &fetched);        // if so, get next pin
    }

    // connect -- 2
    pGraphBuilder->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();

    // find Vweb Mpeg4 Video Decoder output *****************************************
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();        // make sure you release the returned IBaseFilter interface
    if (pinfo.dir == PINDIR_INPUT)        // check if we have wrong pin (not input pin),only 1 input pin
    {
        OutPin->Release();
        EnumPins->Next(1, &OutPin, &fetched);        // if so, get next pin
        OutPin->QueryPinInfo(&pinfo);
        pinfo.pFilter->Release();
        WCHAR *s=pinfo.achName;
    }
    EnumPins->Release();

    // find Overlay Mixer2 input
    pOverlayMaxer2->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);
    InPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();        // make sure you release the returned IBaseFilter interface
    WCHAR *s=pinfo.achName;
    if (pinfo.dir == PINDIR_OUTPUT)        // check if we have wrong pin (not input pin),2 input pin
    {
        InPin->Release();
        EnumPins->Next(1, &InPin, &fetched);        // if so, get next pin
    }
    // connect -- 3
    pGraphBuilder->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();

    // find Overlay Mixer2 output
    EnumPins->Reset();
    EnumPins->Next(1, &OutPin, &fetched);
    OutPin->QueryPinInfo(&pinfo);
    pinfo.pFilter->Release();        // make sure you release the returned IBaseFilter interface
    while (pinfo.dir == PINDIR_INPUT)        // check if we have wrong pin (not input pin),2 input pin
    {
        OutPin->Release();
        EnumPins->Next(1, &OutPin, &fetched);        // if so, get next pin
        OutPin->QueryPinInfo(&pinfo);
        pinfo.pFilter->Release();
        WCHAR *s=pinfo.achName;
    }
    EnumPins->Release();

    // find renderer input
    pVideoRenderer->EnumPins(&EnumPins);
    EnumPins->Reset();
    EnumPins->Next(1, &InPin, &fetched);    // renderer has only 1 pin, so this is the pin we need
    EnumPins->Release();

    // connect -- 4
    pGraphBuilder->Connect(OutPin, InPin);
    InPin->Release();
    OutPin->Release();

    IMediaEvent   *pEvent;
    IMediaControl *pMediaControl;
   // Create the filter graph manager and query for interfaces.
  
    hr=pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
    hr=pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

  
    // Run the graph.
    pMediaControl->Run();

    // Wait for completion.
    long evCode;
    pEvent->WaitForCompletion(INFINITE, &evCode);

    // Clean up.
    pMpeg4PSFileStream->Release();
    pMpegDemuxFilter->Release();
    pMpeg4VideoDecoder->Release();
    pOverlayMaxer2->Release();
    pVideoRenderer->Release();

    pMediaControl->Release();
    pEvent->Release();
    pGraphBuilder->Release();

    delete strPinName;
    CoUninitialize();

长枪大戟的代码都已经包括了,不过听说不在directshow filter里的filter需要枚举才能正常使用,但是我没有试过,不知道是不是,以下代码是枚举捕捉设备的.
HRESULT CCaptureEx::FindCaptureDevice(IBaseFilter **ppSrcFilter)
{
    HRESULT hr;
    IBaseFilter * pSrc = NULL;
    CComPtr <IMoniker> pMoniker =NULL;
    ULONG cFetched;

    if (!ppSrcFilter)
        return E_POINTER;
  
    // Create the system device enumerator
    CComPtr <ICreateDevEnum> pDevEnum =NULL;

    hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
                           IID_ICreateDevEnum, (void **) &pDevEnum);
    if (FAILED(hr))
    {
        Msg(TEXT("Couldn't create system enumerator!  hr=0x%x"), hr);
        return hr;
    }

    // Create an enumerator for the video capture devices
    CComPtr <IEnumMoniker> pClassEnum = NULL;

    hr = pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pClassEnum, 0);
    if (FAILED(hr))
    {
        //Msg(TEXT("Couldn't create class enumerator!  hr=0x%x"), hr);
        return hr;
    }

    // If there are no enumerators for the requested type, then
    // CreateClassEnumerator will succeed, but pClassEnum will be NULL.
    if (pClassEnum == NULL)
    {
       return E_FAIL;
    }

    // Use the first video capture device on the device list.
    // Note that if the Next() call succeeds but there are no monikers,
    // it will return S_FALSE (which is not a failure).  Therefore, we
    // check that the return code is S_OK instead of using SUCCEEDED() macro.
    if (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
    {
        // Bind Moniker to a filter object
        hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc);
        if (FAILED(hr))
        {
            //Msg(TEXT("Couldn't bind moniker to filter object!  hr=0x%x"), hr);
            return hr;
        }
    }
    else
    {
        //Msg(TEXT("Unable to access video capture device!"));  
        return E_FAIL;
    }

    // Copy the found filter pointer to the output parameter.
    // Do NOT Release() the reference, since it will still be used
    // by the calling function.
    *ppSrcFilter = pSrc;

    return hr;
}

 / 根据Filter的DisplayName来获取其IMoniker指针,并将IMoniker指针绑定到一个IBaseFilter指针中
HRESULT CDXGraph::DisplayNameToMoniker(WCHAR * szDisplayName, IBaseFilter ** ppBf)
{
    if (! mGraph || ! szDisplayName|| ! ppBf)
        return E_POINTER;

    IBaseFilter *pFilter = NULL;

    IBindCtx *pBindCtx;
    HRESULT hr = CreateBindCtx(0, &pBindCtx);
    ULONG chEaten = 0;

    CComPtr <IMoniker> pMoniker = NULL;
    hr = MkParseDisplayName(pBindCtx, szDisplayName, &chEaten, &pMoniker);
    pBindCtx->Release();

    if (SUCCEEDED(hr))
    {
        hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,(void **)&pFilter);
        if (FAILED(hr))
        {
            AfxMessageBox(TEXT("Couldn't bind moniker to filter object!"));
            return E_FAIL;
        }

        // Copy the found filter pointer to the output parameter.
        // Do NOT Release() the reference, since it will still be used
        // by the calling function.
        *ppBf = pFilter;

        return hr;
    }
    return hr;
}

//使用xvid mpge4的代码,其中szDisplay存储的是Filter的DisplayName,可以重GraphEdit中查看
    WCHAR szDisplay[] = L"@device:cm:{33D9A760-90C8-11D0-BD43-00A0C911CE86}\\xvid";
    if (SUCCEEDED(mFilterGraph->DisplayNameToMoniker(szDisplay, &pVideoCompressFilter)))
    {
        if (SUCCEEDED(mFilterGraph->GetGraph()->AddFilter(pVideoCompressFilter,L"XVid MPEG-4 Codec")))
        {
            //pVideoCompressFilter->Release();
        }
    }
 

// 获取视频采集的Capture Source Filter和FriendlyName
HRESULT CDXGraph::EnumVideoCaptureSource(IBaseFilter ** ppBf, WCHAR* szFilterName)
{
    if (!mGraph || ! ppBf)
        return E_POINTER;
    // Create the System Device Enumerator.
    IBaseFilter *pFilter = NULL;

    HRESULT hr;
    CComPtr <ICreateDevEnum> pSysDevEnum = NULL;
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
        IID_ICreateDevEnum, (void **)&pSysDevEnum);
    if (FAILED(hr))
    {
        return hr;
    }

    // Obtain a class enumerator for the video capture Source category.
     CComPtr <IEnumMoniker> pEnumCat = NULL;
    hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
    if (FAILED(hr))
    {
        AfxMessageBox("Create class enumerator for the video capture Failed.");
        return hr;
    }

    // If there are no enumerators for the requested type, then
    // CreateClassEnumerator will succeed, but pClassEnum will be NULL.
    if (pEnumCat == NULL)
    {
        CString str("");
        str += TEXT("No video capture device was detected.\r\n\r\n");
        str += TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n");
        str += TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n");
        str += TEXT("This sample requires a video capture device, such as a USB WebCam,\r\n");
        str += TEXT("to be installed and working properly.  The sample will now close.");

        AfxMessageBox(str);
        return E_FAIL;
    }

    // Use the first video capture device on the device list.
    // Note that if the Next() call succeeds but there are no monikers,
    // it will return S_FALSE (which is not a failure).  Therefore, we
    // check that the return code is S_OK instead of using SUCCEEDED() macro.
    CComPtr <IMoniker> pMoniker = NULL;
    ULONG cFetched;
    if(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
            (void **)&pPropBag);
        if (SUCCEEDED(hr))
        {
            // To retrieve the filter's friendly name, do the following:
            VARIANT varName;
            VariantInit(&varName);
            hr = pPropBag->Read(L"FriendlyName", &varName, 0);
            if (SUCCEEDED(hr))
            {
                // Display the name in your UI somehow.
                //使用W2A()、A2W()、T2OLE()、OLE2T()等转换函数需要使用USES_CONVERSION语句
                USES_CONVERSION;
                //varName.bstrVal的值为局部变量,需要将数据复制到数组变量中
                //如果使用指针指向局部变量,则产生错误
                wsprintfW(szFilterName,varName.bstrVal);
                //AfxMessageBox(W2A(szFilterName));
            }
            VariantClear(&varName);
            pPropBag->Release();
            // To create an instance of the filter, do the following:

            hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,(void **)&pFilter);
            if (FAILED(hr))
            {
                AfxMessageBox(TEXT("Couldn't bind moniker to filter object!"));
                return hr;
            }
        }
        else
        {
            AfxMessageBox(TEXT("Unable to access video capture device!"));  
            return E_FAIL;
        }
        // Copy the found filter pointer to the output parameter.
        // Do NOT Release() the reference, since it will still be used
        // by the calling function.
        *ppBf = pFilter;

        return hr;
    }
    return hr;
}

posted on 2005-04-29 11:51  ____Justin____  阅读(1967)  评论(0编辑  收藏  举报