欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

视频捕获增加color space converter + Transform Filter

程序员文章站 2022-06-19 17:18:36
其它不解释,贴是代码: ipfilter.h [html] //  // sample directshow in-place 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; 
    } 

调用:

[html] 
lpcwstr wchfile=l"d:\\example.avi"; 
        m_graph.buildfromfile(wchfile); 
        m_graph.makechild(getsafehwnd()); 
        m_graph.run(); 

视频捕获增加color space converter + Transform Filter
作者:luckyboy101