Transform Filter 代码(转)

视频捕获增加color space converter +

Transform Filter

其它不解释,贴是代码:

IPFilter.h

[html]
// 
// Sample DirectShow In-Place Transform Filter that accepts data for use in application 
// 
 
#include <streams.h> 
 
// This is an example transform filter that is created within 
// the application, and not by CoCreateInstance 
class CAppTransform : public CTransformFilter 

public: 
    CAppTransform(LPUNKNOWN pUnkOuter, HRESULT *phr); 
 
    HRESULT CheckInputType(const CMediaType* mtIn); 
     
    HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut); 
    HRESULT CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut); 
    HRESULT DecideBufferSize(IMemAllocator *pAlloc, 
        ALLOCATOR_PROPERTIES *pProperties); 
    HRESULT GetMediaType(int iPosition, CMediaType *pMediaType); 
private: 
    HRESULT Copy(IMediaSample *pSource, IMediaSample *pDest) const; 
    HRESULT Transform(IMediaSample *pSample); 
}; 
 
 
// DirectShow graph management sample code: 
// This builds a playback graph using RenderFile 
// and then inserts a transform filter on the uncompressed video. 
class CAppGraphBuilder 

private: 
    CAppTransform*   m_pFilter; 
    DWORD            m_dwObjectTable;  
    ICaptureGraphBuilder2 *m_pBuild; 
    IGraphBuilder *m_pGraph; 
 
public: 
    CAppGraphBuilder(); 
    ~CAppGraphBuilder(); 
 
    void DestroyGraph(void); 
 
    HRESULT BuildFromFile(LPCWSTR pszFile); 
    HRESULT Run(void); 
    HRESULT MakeChild(HWND hwnd); 
    HRESULT ResizeVideoWindow(RECT* prc); 
 
private: 
    void CreateAppFilter(void); 
    HRESULT FindFilterByInterface(REFIID riid, IBaseFilter** ppFilter); 
    HRESULT ConnectUpstreamOf(IBaseFilter* pFilter,IBaseFilter*pColor, IBaseFilter* pTransform); 
    HRESULT NextUpstream(IBaseFilter* pFilter, IBaseFilter** ppNext);   
    HRESULT CAppGraphBuilder::AddFilterByCLSID(IGraphBuilder *pGraph,const GUID& clsid,LPCWSTR wszName,IBaseFilter **ppF); 
     
    HRESULT InitCaptureGraphBuilder(IGraphBuilder **ppGraph,ICaptureGraphBuilder2 **ppBuild); 
    HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum); 
    void DisplayDeviceInformation(IEnumMoniker *pEnum, IMoniker** pMoniker); 
 
    IPin* GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirRequest); 
    // Helper methods 
    IPin* InputPinOf(IBaseFilter* pFilter)  
    { 
        return GetPin(pFilter, PINDIR_INPUT); 
    } 
    IPin* OutputPinOf(IBaseFilter* pFilter)  
    { 
        return GetPin(pFilter, PINDIR_OUTPUT); 
    } 
 
    void AddToObjectTable(void) ; 
    void RemoveFromObjectTable(void); 
}; 

IPFilter.cpp

[html] view plaincopy
// 
// Sample DirectShow Transform Filter that accepts data for use in application 
// 
 
#include "stdafx.h" 
#include "IPFilter.h" 
 
 
CAppTransform::CAppTransform(LPUNKNOWN pUnkOuter, HRESULT *phr) :  
CTransformFilter(NAME("App Transform"), pUnkOuter, GUID_NULL) 


// 
// CheckTransform 
// 
// To be able to transform the formats must be identical 
// 
HRESULT CAppTransform::CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut) 

    CheckPointer(mtIn,E_POINTER); 
    CheckPointer(mtOut,E_POINTER); 
 
    HRESULT hr; 
    if(FAILED(hr = CheckInputType(mtIn))) 
    { 
        return hr; 
    } 
 
    // format must be a VIDEOINFOHEADER 
    if(*mtOut->FormatType() != FORMAT_VideoInfo) 
    { 
        return E_INVALIDARG; 
    } 
 
    // formats must be big enough  
    if(mtIn->FormatLength() < sizeof(VIDEOINFOHEADER) || 
        mtOut->FormatLength() < sizeof(VIDEOINFOHEADER)) 
        return E_INVALIDARG; 
 
    VIDEOINFO *pInput  = (VIDEOINFO *) mtIn->Format(); 
    VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format(); 
 
    if(memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0) 
    { 
        return NOERROR; 
    } 
 
    return E_INVALIDARG; 
 
} // CheckTransform 
// 
// DecideBufferSize 
// 
// Tell the output pin's allocator what size buffers we 
// require. Can only do this when the input is connected 
// 
HRESULT CAppTransform::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties) 

    CheckPointer(pAlloc,E_POINTER); 
    CheckPointer(pProperties,E_POINTER); 
 
    // Is the input pin connected 
 
    if(m_pInput->IsConnected() == FALSE) 
    { 
        return E_UNEXPECTED; 
    } 
    HRESULT hr = NOERROR; 
    pProperties->cBuffers = 1; 
    pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize(); 
 
    ASSERT(pProperties->cbBuffer); 
 
    // If we don't have fixed sized samples we must guess some size 
 
    if(!m_pInput->CurrentMediaType().bFixedSizeSamples) 
    { 
        if(pProperties->cbBuffer < 100000) 
        { 
            // nothing more than a guess!! 
            pProperties->cbBuffer = 100000; 
        } 
    } 
 
    // Ask the allocator to reserve us some sample memory, NOTE the function 
    // can succeed (that is return NOERROR) but still not have allocated the 
    // memory that we requested, so we must check we got whatever we wanted 
 
    ALLOCATOR_PROPERTIES Actual; 
 
    hr = pAlloc->SetProperties(pProperties,&Actual); 
    if(FAILED(hr)) 
    { 
        return hr; 
    } 
 
    ASSERT(Actual.cBuffers == 1); 
 
    if(pProperties->cBuffers > Actual.cBuffers || 
        pProperties->cbBuffer > Actual.cbBuffer) 
    { 
        return E_FAIL; 
    } 
 
    return NOERROR; 
 
} // DecideBufferSize 
// 
// GetMediaType 
// 
// I support one type, namely the type of the input pin 
// We must be connected to support the single output type 
// 
HRESULT CAppTransform::GetMediaType(int iPosition, CMediaType *pMediaType) 

    // Is the input pin connected 
 
    if(m_pInput->IsConnected() == FALSE) 
    { 
        return E_UNEXPECTED; 
    } 
 
    // This should never happen 
 
    if(iPosition < 0) 
    { 
        return E_INVALIDARG; 
    } 
 
    // Do we have more items to offer 
 
    if(iPosition > 0) 
    { 
        return VFW_S_NO_MORE_ITEMS; 
    } 
 
    CheckPointer(pMediaType,E_POINTER); 
 
    *pMediaType = m_pInput->CurrentMediaType(); 
    return NOERROR; 
 

HRESULT CAppTransform::Copy(IMediaSample *pSource, IMediaSample *pDest) const 

    CheckPointer(pSource,E_POINTER); 
    CheckPointer(pDest,E_POINTER); 
 
    // Copy the sample data 
    BYTE *pSourceBuffer, *pDestBuffer; 
    long lSourceSize = pSource->GetActualDataLength(); 
 
#ifdef DEBUG 
    long lDestSize = pDest->GetSize(); 
    ASSERT(lDestSize >= lSourceSize); 
#endif 
 
    pSource->GetPointer(&pSourceBuffer); 
    pDest->GetPointer(&pDestBuffer); 
 
    CopyMemory((PVOID) pDestBuffer,(PVOID) pSourceBuffer,lSourceSize); 
 
    // Copy the sample times 
 
    REFERENCE_TIME TimeStart, TimeEnd; 
    if(NOERROR == pSource->GetTime(&TimeStart, &TimeEnd)) 
    { 
        pDest->SetTime(&TimeStart, &TimeEnd); 
    } 
 
    LONGLONG MediaStart, MediaEnd; 
    if(pSource->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) 
    { 
        pDest->SetMediaTime(&MediaStart,&MediaEnd); 
    } 
 
    // Copy the Sync point property 
 
    HRESULT hr = pSource->IsSyncPoint(); 
    if(hr == S_OK) 
    { 
        pDest->SetSyncPoint(TRUE); 
    } 
    else if(hr == S_FALSE) 
    { 
        pDest->SetSyncPoint(FALSE); 
    } 
    else 
    {  // an unexpected error has occured... 
        return E_UNEXPECTED; 
    } 
 
    // Copy the media type 
 
    AM_MEDIA_TYPE *pMediaType; 
    pSource->GetMediaType(&pMediaType); 
    pDest->SetMediaType(pMediaType); 
    DeleteMediaType(pMediaType); 
 
    // Copy the preroll property 
 
    hr = pSource->IsPreroll(); 
    if(hr == S_OK) 
    { 
        pDest->SetPreroll(TRUE); 
    } 
    else if(hr == S_FALSE) 
    { 
        pDest->SetPreroll(FALSE); 
    } 
    else 
    {  // an unexpected error has occured... 
        return E_UNEXPECTED; 
    } 
 
    // Copy the discontinuity property 
 
    hr = pSource->IsDiscontinuity(); 
 
    if(hr == S_OK) 
    { 
        pDest->SetDiscontinuity(TRUE); 
    } 
    else if(hr == S_FALSE) 
    { 
        pDest->SetDiscontinuity(FALSE); 
    } 
    else 
    {  // an unexpected error has occured... 
        return E_UNEXPECTED; 
    } 
 
    // Copy the actual data length 
 
    long lDataLength = pSource->GetActualDataLength(); 
    pDest->SetActualDataLength(lDataLength); 
 
    return NOERROR; 
 
} // Copy 
// 
// Transform 
// 
// Copy the input sample into the output sample 
// Then transform the output sample 'in place' 
// 
HRESULT CAppTransform::Transform(IMediaSample *pIn, IMediaSample *pOut) 

    HRESULT hr = Copy(pIn, pOut); 
    if (FAILED(hr)) { 
        return hr; 
    } 
 
    return Transform(pOut); 
 
 
} // Transform 
HRESULT CAppTransform::Transform(IMediaSample *pSample) 

    // Override to do something inside the application 
    // Such as grabbing a poster frame... 
    // ... 
    BYTE *pData;                // Pointer to the actual image buffer 
    long lDataLen;              // Holds length of any given sample 
    int iPixel;                 // Used to loop through the image pixels 
    tagRGBTRIPLE *prgb;            // Holds a pointer to the current pixel 
 
    AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType(); 
    VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat; 
    ASSERT(pvi); 
 
    CheckPointer(pSample,E_POINTER); 
    pSample->GetPointer(&pData); 
    lDataLen = pSample->GetSize(); 
 
    // Get the image properties from the BITMAPINFOHEADER 
 
    int cxImage    = pvi->bmiHeader.biWidth; 
    int cyImage    = pvi->bmiHeader.biHeight; 
    int numPixels  = cxImage * cyImage; 
 
    // int iPixelSize = pvi->bmiHeader.biBitCount / 8; 
    // int cbImage    = cyImage * cxImage * iPixelSize; 
 
 
    prgb = (tagRGBTRIPLE*) pData; 
    for (iPixel=0; iPixel < numPixels; iPixel++, prgb++) { 
    prgb->rgbtRed=prgb->rgbtBlue=prgb->rgbtGreen=(prgb->rgbtRed+prgb->rgbtBlue+prgb->rgbtGreen)/3; 
    } 
    return S_OK; 

 
// Check if we can support this specific proposed type and format 
HRESULT CAppTransform::CheckInputType(const CMediaType *pmt)  

    // We accept a series of raw media types 
    /*if (pmt->majortype == MEDIATYPE_Video && 
    (pmt->subtype == MEDIASUBTYPE_RGB32 || 
    pmt->subtype == MEDIASUBTYPE_RGB24 || 
    pmt->subtype == MEDIASUBTYPE_RGB565 || 
    pmt->subtype == MEDIASUBTYPE_RGB555 || 
    pmt->subtype == MEDIASUBTYPE_UYVY || 
    pmt->subtype == MEDIASUBTYPE_YUY2)|| 
    pmt->subtype==MEDIASUBTYPE_NV12)*/ 
    if (pmt->majortype == MEDIATYPE_Video && 
        (pmt->subtype == MEDIASUBTYPE_RGB24)) 
    { 
        return NOERROR; 
    } 
    return E_FAIL; 

 
 
// --- graph building (examples) ---------  
CAppGraphBuilder::CAppGraphBuilder() :  
m_pBuild(NULL), 
m_pGraph(NULL), 
m_pFilter(NULL), 
m_dwObjectTable(0) 

    CoInitialize(NULL); 

 
CAppGraphBuilder::~CAppGraphBuilder() 

    DestroyGraph(); 
    CoUninitialize(); 

     
void CAppGraphBuilder::DestroyGraph(void) 

    if (m_pGraph)  
    { 
        RemoveFromObjectTable(); 
        // ensure graph window is not child of ours 
        IVideoWindow* pVW = NULL; 
        HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW); 
        if (SUCCEEDED(hr))  
        { 
            pVW->put_Visible(OAFALSE); 
            pVW->put_Owner(NULL); 
            pVW->put_MessageDrain(NULL); 
            pVW->Release(); 
        } 
        m_pGraph->Release(); 
        m_pGraph = NULL; 
        m_pBuild->Release(); 
        m_pBuild = NULL; 
    } 
 
    if (m_pFilter)  
    { 
        m_pFilter->Release(); 
        m_pFilter = NULL; 
    } 

HRESULT CAppGraphBuilder::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 

 
 
 
HRESULT CAppGraphBuilder::EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum) 

    ICreateDevEnum *pDevEnum = NULL; 
 
    // Create the System Device Enumerator. 
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 
        CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,  
        reinterpret_cast<void**>(&pDevEnum)); 
    if (SUCCEEDED(hr)) 
    { 
        // Create an enumerator for the video capture category. 
        hr = pDevEnum->CreateClassEnumerator( 
            CLSID_VideoInputDeviceCategory, 
            ppEnum, 0); 
    } 
    return hr; 

void CAppGraphBuilder::DisplayDeviceInformation(IEnumMoniker *pEnum, IMoniker** pMoniker) 

    HWND hList; // Handle to the list box. 
    while (pEnum->Next(1, pMoniker, NULL) == S_OK) 
    { 
        IPropertyBag *pPropBag; 
        HRESULT hr = (*pMoniker)->BindToStorage(0, 0, IID_IPropertyBag,  
            (void**)(&pPropBag)); 
        if (FAILED(hr)) 
        { 
            (*pMoniker)->Release(); 
            continue;  // Skip this one, maybe the next one will work. 
        }  
        // Find the description or friendly name. 
        VARIANT varName; 
        VariantInit(&varName); 
        hr = pPropBag->Read(L"Description", &varName, 0); 
        if (FAILED(hr)) 
        { 
            hr = pPropBag->Read(L"FriendlyName", &varName, 0); 
        } 
        if (SUCCEEDED(hr)) 
        { 
            // Add it to the application's list box. 
            USES_CONVERSION; 
            /*(long)SendMessage(hList, LB_ADDSTRING, 0,  
            (LPARAM)OLE2T(varName.bstrVal));*/ 
            VariantClear(&varName);  
        } 
        pPropBag->Release(); 
        (*pMoniker)->Release(); 
    } 
 
 

HRESULT CAppGraphBuilder::AddFilterByCLSID( 
    IGraphBuilder *pGraph,  // Pointer to the Filter Graph Manager. 
    const GUID& clsid,      // CLSID of the filter to create. 
    LPCWSTR wszName,        // A name for the filter. 
    IBaseFilter **ppF)      // Receives a pointer to the filter. 

    if (!pGraph || ! ppF) return E_POINTER; 
    *ppF = 0; 
    IBaseFilter *pF = 0; 
    HRESULT hr = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, 
        IID_IBaseFilter, reinterpret_cast<void**>(&pF)); 
    if (SUCCEEDED(hr)) 
    { 
        hr = pGraph->AddFilter(pF, wszName); 
        if (SUCCEEDED(hr)) 
            *ppF = pF; 
        else 
            pF->Release(); 
    } 
    return hr; 

HRESULT CAppGraphBuilder::BuildFromFile(LPCWSTR pszFile) 

    DestroyGraph(); 
    IMoniker* pMoniker; 
     
    IMediaEvent   *pEvent; 
 
    InitCaptureGraphBuilder(&m_pGraph,&m_pBuild); 
     
    HRESULT hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); 
 
    AddToObjectTable(); 
    IBaseFilter *pCap; // Video capture filter. 
    IEnumMoniker *pEnum; 
 
    hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum); 
 
    DisplayDeviceInformation(pEnum, &pMoniker); 
    hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); 
    if (SUCCEEDED(hr)) 
    { 
        hr = m_pGraph->AddFilter(pCap, L"Capture Filter"); 
    } 
    hr = m_pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL); 
 
 
    IBaseFilter *pMux; 
    hr = m_pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi,L"D:\\Example.avi",&pMux,NULL); 
    hr = m_pBuild->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,pCap,NULL,pMux); 
 
     
     
    // Try to find the video renderer, by looking for IVideoWindow 
    IBaseFilter* pVR; 
    hr = FindFilterByInterface(IID_IVideoWindow, &pVR); 
    if (FAILED(hr))  
    { 
        return hr; 
    } 
 
    // Find the media type on the input pin of the Video Renderer 
    // to check for overlay connection where no actual data is passed 
    IPin* pPin = InputPinOf(pVR); 
    AM_MEDIA_TYPE mt; 
    pPin->ConnectionMediaType(&mt); 
    pPin->Release(); 
    CMediaType mtIn = mt; 
    FreeMediaType(mt); 
 
    if (mtIn.subtype == MEDIASUBTYPE_Overlay)  
    { 
        // This connection may be a overlay mixer  
        // need to move upstream one place 
        IBaseFilter* pOvMix = NULL; 
        hr = NextUpstream(pVR, &pOvMix); 
        pVR->Release(); 
        if (FAILED(hr))  
        { 
            return hr; 
        } 
        pVR = pOvMix; 
    } 
 
    // Create the transform and insert in graph 
    CreateAppFilter(); 
 
    // Add Color Space Convert 
    IBaseFilter *pColor; 
    hr=AddFilterByCLSID(m_pGraph, CLSID_Colour, L"Color Space Converter", &pColor); 
 
    // Try to insert our transform filter 
    hr = ConnectUpstreamOf(pVR, pColor,m_pFilter); 
    //pVR->Release(); 
 
     
    //pColor->Release(); 
 
    return hr; 

 
// Start the graph 
HRESULT CAppGraphBuilder::Run(void) 

    IMediaControl* pControl = NULL; 
    HRESULT hr = m_pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl); 
    if (SUCCEEDED(hr))  
    { 
        hr = pControl->Run(); 
        pControl->Release(); 
    } 
    return hr; 

 
// Make the video window a child of this app 
HRESULT CAppGraphBuilder::MakeChild(HWND hwnd) 

    if (!m_pGraph)  
    { 
        return E_FAIL; 
    } 
 
    IVideoWindow* pVW = NULL; 
    HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW); 
    if (SUCCEEDED(hr))  
    { 
        HWND hwndOld; 
        pVW->get_Owner((LONG*)&hwndOld); 
        if (hwndOld != hwnd) 
        { 
            pVW->put_AutoShow(OAFALSE); 
            pVW->put_Visible(OAFALSE); 
             
            long    WindowStyle = 0; 
            // Tweak the video's window style to get rid of the caption and frame: 
            hr = pVW->get_WindowStyle(&WindowStyle); 
            if (SUCCEEDED(hr))  
            { 
                WindowStyle &= ~WS_OVERLAPPEDWINDOW; // No frame junk 
                WindowStyle |= WS_CHILD;             // Needs to be child 
                hr = pVW->put_WindowStyle(WindowStyle); 
            } 
 
            pVW->put_Owner((LONG)hwnd); 
            pVW->put_MessageDrain((LONG)hwnd); 
 
            if (hwnd != NULL)  
            { 
                RECT rc; 
                GetClientRect(hwnd, &rc); 
                pVW->SetWindowPosition( 
                        rc.left, 
                        rc.top, 
                        rc.right - rc.left, 
                        rc.bottom - rc.top); 
                pVW->put_Visible(OATRUE); 
            } 
        } 
        pVW->Release(); 
    } 
 
    return hr; 

 
// Resize the video window 
HRESULT CAppGraphBuilder::ResizeVideoWindow(RECT* prc) 

    if (!m_pGraph)  
    { 
        return E_FAIL; 
    } 
 
    IVideoWindow* pVW = NULL; 
    HRESULT hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVW); 
    if (SUCCEEDED(hr))  
    { 
        hr = pVW->SetWindowPosition( 
            prc->left, 
            prc->top, 
            prc->right - prc->left, 
            prc->bottom - prc->top); 
        pVW->Release(); 
    } 
    return hr; 

 
// Create the app-based filter and insert into graph (unconnected) 
void CAppGraphBuilder::CreateAppFilter(void) 

    if (m_pFilter)  
    { 
        m_pFilter->Release(); 
        m_pFilter = NULL; 
    } 
 
    HRESULT hr = S_OK; 
    m_pFilter = new CAppTransform(NULL, &hr); 
    // Make the initial refcount 1 to match COM creation!!! 
    m_pFilter->AddRef(); 
 
    // Add to graph -- nb need to Query properly for the 
    // right interface before giving that to the graph object 
    IBaseFilter* pFilter = NULL; 
    hr = m_pFilter->QueryInterface(IID_IBaseFilter, (void**)&pFilter); 
    if (SUCCEEDED(hr))  
    { 
        hr = m_pGraph->AddFilter(pFilter, L"App Transform"); 
        pFilter->Release(); 
    } 

 
// Locate a filter within the graph by searching (from renderers upstream) 
// looking for a specific interface on the filter 
HRESULT CAppGraphBuilder::FindFilterByInterface(REFIID riid, IBaseFilter** ppFilter) 

    *ppFilter = NULL; 
 
    IEnumFilters* pEnum; 
    HRESULT hr = m_pGraph->EnumFilters(&pEnum); 
    if (FAILED(hr))  
    { 
        return hr; 
    } 
 
    IBaseFilter* pFilter = NULL; 
    while (pEnum->Next(1, &pFilter, NULL) == S_OK)  
    { 
        // Check for required interface 
        IUnknown* pUnk; 
        HRESULT hrQuery = pFilter->QueryInterface(riid, (void**)&pUnk); 
        if (SUCCEEDED(hrQuery))  
        { 
            pUnk->Release(); 
            pEnum->Release(); 
            *ppFilter = pFilter; 
            return S_OK; 
        } 
        pFilter->Release(); 
    } 
    pEnum->Release(); 
 
    return E_FAIL; 

 
 
// Connect the filter pTransform upstream of pFilter by reconnecting pins. 
// Assumes that pTransform has only one input and one output, and 
// that pFilter has only one input. 
HRESULT CAppGraphBuilder::ConnectUpstreamOf(IBaseFilter* pFilter, IBaseFilter*pColor,IBaseFilter* pTransform) 

    IPin* pPinIn = InputPinOf(pFilter); 
    if (!pPinIn)  
    { 
        return E_FAIL; 
    } 
 
    // Get the peer output pin 
    IPin* pPinOut = NULL; 
    HRESULT hr = pPinIn->ConnectedTo(&pPinOut); 
    if (FAILED(hr))  
    { 
        pPinIn->Release(); 
        return hr; 
    } 
 
    // Disconnect the current connection 
    hr = m_pGraph->Disconnect(pPinOut); 
    if (SUCCEEDED(hr))  
    { 
        hr = m_pGraph->Disconnect(pPinIn); 
    } 
 
    // Insert pTransform filter by connecting its input pin and output pin 
    if (SUCCEEDED(hr))  
    { 
        IPin* pPinInCor = InputPinOf(pColor); 
        hr = m_pGraph->Connect(pPinOut, pPinInCor); 
        pPinInCor->Release(); 
    } 
    if (SUCCEEDED(hr))  
    { 
        IPin* pPinInXfm = InputPinOf(pTransform); 
        IPin* pPinOutCor = OutputPinOf(pColor); 
        hr = m_pGraph->Connect(pPinOutCor, pPinInXfm); 
        pPinInXfm->Release(); 
        pPinOutCor->Release(); 
    } 
    if (SUCCEEDED(hr))  
    { 
        IPin* pPinOutXfm = OutputPinOf(pTransform); 
        hr = m_pGraph->Connect(pPinOutXfm, pPinIn); 
        pPinOutXfm->Release(); 
    } 
     
    pPinIn->Release(); 
    pPinOut->Release(); 
    return hr; 

 
// Find the first pin of a specific direction on a given filter 
IPin* CAppGraphBuilder::GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirRequest) 

    IPin * foundPin = NULL; 
 
    IEnumPins* pEnum = NULL; 
    HRESULT hr = pFilter->EnumPins(&pEnum); 
    if (SUCCEEDED(hr))  
    { 
        IPin* pPin = NULL; 
        while (!foundPin && pEnum->Next(1, &pPin, 0) == S_OK)  
        { 
            PIN_DIRECTION dir; 
            pPin->QueryDirection(&dir); 
            if (dir == dirRequest)  
            { 
                foundPin = pPin; 
            } 
            else 
            { 
                pPin->Release(); 
            } 
        } 
        pEnum->Release(); 
    } 
    return foundPin; 

 
// Follow the pin connections to return the filter that is  
// connected to the first input pin of pFilter 
HRESULT CAppGraphBuilder::NextUpstream(IBaseFilter* pFilter, IBaseFilter** ppNext) 

    IPin* pPin = InputPinOf(pFilter); 
    if (!pPin)  
    { 
        return E_FAIL; 
    } 
 
    // Get the peer output pin 
    IPin* pPinOut = NULL; 
    HRESULT hr = pPin->ConnectedTo(&pPinOut); 
    pPin->Release(); 
    if (FAILED(hr))  
    { 
        return hr; 
    } 
 
    PIN_INFO info; 
    pPinOut->QueryPinInfo(&info); 
    pPinOut->Release(); 
    *ppNext = info.pFilter; 
     
    return S_OK; 

 
 
 
For GraphEdit Dubug purpose / 
void CAppGraphBuilder::AddToObjectTable(void) 

    IMoniker * pMoniker = 0; 
    IRunningObjectTable * objectTable = 0; 
    if (SUCCEEDED(GetRunningObjectTable(0, &objectTable)))  
    { 
        WCHAR wsz[256]; 
        wsprintfW(wsz, L"FilterGraph %08p pid %08x", (DWORD_PTR)m_pGraph, GetCurrentProcessId()); 
        HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker); 
        if (SUCCEEDED(hr))  
        { 
            hr = objectTable->Register(0, m_pGraph, pMoniker, &m_dwObjectTable); 
            pMoniker->Release(); 
        } 
        objectTable->Release(); 
    } 

 
void CAppGraphBuilder::RemoveFromObjectTable(void) 

    IRunningObjectTable * objectTable = 0; 
    if (SUCCEEDED(GetRunningObjectTable(0, &objectTable)))  
    { 
        objectTable->Revoke(m_dwObjectTable); 
        objectTable->Release(); 
        m_dwObjectTable = 0; 
    } 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我理解了你的问题。要用 VTK 实现一个 transform filter,可以按以下步骤进行: 1. 创建一个 VTK 数据源,可以是任何类型的数据集,例如 vtkPolyData 或 vtkImageData。 2. 创建一个 vtkTransform 对象,用于定义你要进行的变换。 3. 创建一个 vtkTransformFilter 对象,并将数据源作为输入。 4. 将 vtkTransform 对象设置为 vtkTransformFilter 的变换。 5. 使用 vtkTransformFilter 的 Update() 方法更新输出数据。 下面是一个示例代码,可以将 vtkPolyData 沿 x 轴平移 5 个单位: ```c++ #include <vtkSmartPointer.h> #include <vtkPolyData.h> #include <vtkTransform.h> #include <vtkTransformFilter.h> int main() { // 创建一个 VTK 数据源 vtkSmartPointer<vtkPolyData> input = vtkSmartPointer<vtkPolyData>::New(); // 创建一个 vtkTransform 对象 vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); transform->Translate(5.0, 0.0, 0.0); // 创建一个 vtkTransformFilter 对象,并将数据源作为输入 vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New(); transformFilter->SetInputData(input); // 将 vtkTransform 对象设置为 vtkTransformFilter 的变换 transformFilter->SetTransform(transform); // 更新输出数据 transformFilter->Update(); // 获取输出数据 vtkSmartPointer<vtkPolyData> output = transformFilter->GetOutput(); return 0; } ``` 希望这个示例能够帮助你实现你的 transform filter

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值