CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Dec 2010
    Posts
    121

    How to create a directshow video capture filter?

    After creating a capture graph builder, how can I directly query a video capture filter? The example I have only got an enumerator for all devices thru monkiers... is it the only path I need to use?
    Thanks
    Jack
    Last edited by luckiejacky; December 31st, 2017 at 11:42 PM.

  2. #2
    Join Date
    Mar 2017
    Posts
    105

    Re: How to create a directshow video capture filter?

    Well, though you have to write the code by yourself, I can provide some code snippets.
    1.Pin requirements for capture filters.
    Code:
    // Set: Cannot set any properties.
    HRESULT CMyCapturePin::Set(REFGUID guidPropSet, DWORD dwID,
        void *pInstanceData, DWORD cbInstanceData, void *pPropData, 
        DWORD cbPropData)
    {
        return E_NOTIMPL;
    }
    
    // Get: Return the pin category (our only property). 
    HRESULT CMyCapturePin::Get(
        REFGUID guidPropSet,   // Which property set.
        DWORD dwPropID,        // Which property in that set.
        void *pInstanceData,   // Instance data (ignore).
        DWORD cbInstanceData,  // Size of the instance data (ignore).
        void *pPropData,       // Buffer to receive the property data.
        DWORD cbPropData,      // Size of the buffer.
        DWORD *pcbReturned     // Return the size of the property.
    )
    {
        if (guidPropSet != AMPROPSETID_Pin) 
            return E_PROP_SET_UNSUPPORTED;
        if (dwPropID != AMPROPERTY_PIN_CATEGORY)
            return E_PROP_ID_UNSUPPORTED;
        if (pPropData == NULL && pcbReturned == NULL)
            return E_POINTER;
        if (pcbReturned)
            *pcbReturned = sizeof(GUID);
        if (pPropData == NULL)  // Caller just wants to know the size.
            return S_OK;
        if (cbPropData < sizeof(GUID)) // The buffer is too small.
            return E_UNEXPECTED;
        *(GUID *)pPropData = PIN_CATEGORY_CAPTURE;
        return S_OK;
    }
    
    // QuerySupported: Query whether the pin supports the specified property.
    HRESULT CMyCapturePin::QuerySupported(REFGUID guidPropSet, DWORD dwPropID,
        DWORD *pTypeSupport)
    {
        if (guidPropSet != AMPROPSETID_Pin)
            return E_PROP_SET_UNSUPPORTED;
        if (dwPropID != AMPROPERTY_PIN_CATEGORY)
            return E_PROP_ID_UNSUPPORTED;
        if (pTypeSupport)
            // We support getting this property, but not setting it.
            *pTypeSupport = KSPROPERTY_SUPPORT_GET; 
        return S_OK;
    }
    2.Implementing a preview pin (that’s completely optional)
    Code:
    // Override CBasePin::CheckMediaType.
    CCapturePin::CheckMediaType(CMediaType *pmt)
    {
        if (m_pMyPreviewPin->IsConnected()) 
        {
            // The preview pin is already connected, so query the pin it is
            // connected to. If the other pin rejects it, so do we.
            hr = m_pMyPreviewPin->GetConnected()->QueryAccept(pmt);
            if (hr != S_OK) 
            {
                // The preview pin cannot reconnect with this media type.
                return E_INVALIDARG;
            }
            // The preview pin will reconnect when SetMediaType is called.
        }
        // Decide whether the capture pin accepts the format. 
        BOOL fAcceptThisType = ...  // (Not shown.)
        return (fAcceptThisType? S_OK : E_FAIL);
    }
    
    // Override CBasePin::SetMediaType.
    CCapturePin::SetMediaType(CMediaType *pmt);
    {
        if (m_pMyPreviewPin->IsConnected()) 
        {
            // The preview pin is already connected, so it must reconnect.
            if (m_pMyPreviewPin->GetConnected()->QueryAccept(pmt) == S_OK)
            {
                // The downstream pin will accept the new type, so it's safe
                // to reconnect. 
                m_pFilter->m_pGraph->Reconnect(m_pMyPreviewPin);
            }
            else
            {
                return VFW_E_INVALIDMEDIATYPE;
            }
        }
        // Now do anything that the capture pin needs to set the type.
        hr = MyInternalSetMediaType(pmt);
    
        // And finally, call the base-class method.
        return CBasePin::SetMediaType(pmt);
    }
    
    CPreviewPin::CheckMediaType(CMediaType *pmt)
    {
        if (m_pMyCapturePin->IsConnected())
        {
           // The preview pin must connect with the same type.
           CMediaType cmt = m_pMyCapturePin->m_mt;
           return (*pmt == cmt ? S_OK : VFW_E_INVALIDMEDIATYPE);
        }
        // Decide whether the preview pin accepts the format. You can use your 
        // knowledge of which types the capture pin will accept. Regardless,
        // when the capture pin connects, the preview pin will reconnect.
        return (fAcceptThisType? S_OK : E_FAIL);
    }
    3. Producing data in capture filter (that’s completely your code, just a small snippet for help)
    Code:
    CMyVidcapFilter::GetState(DWORD dw, FILTER_STATE *pState)
    {
        CheckPointer(pState, E_POINTER);
        *pState = m_State;
        if (m_State == State_Paused)
        {
            return VFW_S_CANT_CUE;
        }
        else
        {
            return S_OK;
        }
    }
    If you like my answer, do rate my post.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured