Create a DirectShow application

Source: Internet
Author: User

There are generally three steps to creating an DShow application:

1. Create a Filter Graph Manager component.

Igraphbuilder * pgraph = NULL;

HRESULT hr = CoCreateInstance (Clsid_filtergraph, NULL,

Clsctx_inproc_server, Iid_igraphbuilder, (void**) &pgraph);

2. According to the actual application, create a filter chain, such as playing a local file, the simplest and fastest code is as follows:

hr = Pgraph->renderfile (L "path", NULL);

3. Call the various interfaces on the Filter Graph manager to control and complete the interaction of the filter Graph manager with the application, such as invoking the IMediaControl interface method to control the state transitions of the filter graph.

IMediaControl *pcontrol = NULL;

hr = Pgraph->queryinterface (Iid_imediacontrol, (void**) Pcontrol);

hr = Pcontrol->run ();


Common Filter Graph construction techniques:

1. Add a filter for the specified CLSID

Given the CLSID of a filter, you can call CoCreateInstance to create it. and add it to the filter graph using the Ifiltergraph::addfilter interface.

The code is as follows:

HRESULT 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;}



To add an AVI Mux filter to the filter graph

Ibasefilter *pmux;

hr = Addfilterbyclsid (pgraph, Clsid_avidest, L "AVI Mux", &pmux);

if (SUCCEEDED (HR))

{

/*...*/

Pmux->release ();

}


2. Get the disconnected pin on the filter

When you connect a filter to a program, you first get the PIN or output pin that is not connected to the filter. The method is to enumerate all the pins on the filter and call the Ipin::querydirection to query the direction of the pin. Then call Ipin::connectedto to view the connection status of the PIN.

HRESULT Getunconnectedpin (Ibasefilter *pfilter,//Pointer to the filter.    Pin_direction Pindir,//DIRECTION of the pin to find. Ipin **pppin)//receives a pointer to the PIN.    {*pppin = 0;    Ienumpins *penum = 0;    Ipin *ppin = 0;    HRESULT hr = Pfilter->enumpins (&penum);    if (FAILED (HR)) {return hr;        } while (Penum->next (1, &ppin, NULL) = = S_OK) {pin_direction thispindir;        Ppin->querydirection (&thispindir);            if (Thispindir = = Pindir) {Ipin *ptmp = 0;            hr = Ppin->connectedto (&ptmp);            if (SUCCEEDED (HR))//already connected, not the pin we want.            {ptmp->release ();            } else//unconnected, this is the pin we want.                {penum->release ();                *pppin = Ppin;            return S_OK;    }} ppin->release ();    } penum->release (); // Did not find a matching pin. return E_FAIL;}


For example, now to get an output pin that is not connected

Ipin *pout = NULL;

HRESULT hr = Getunconnectedpin (PFilter, Pindir_output, &pout);

if (SUCCEEDED (HR))

{

/*...*/

Pout->release ();

}


3. Connect two filter

The functions that connect two filter in filter graph are ifiltergraph::connectdirect and ifiltergraph::connect

HRESULT connectfilters (    igraphbuilder *pgraph,//Filter Graph Manager.    Ipin *pout,            //Output pin on the upstream filter.    Ibasefilter *pdest)    //downstream filter.{    if ((pgraph = = NULL) | | (POut = = NULL) | | (PDest = = NULL))    {        return e_pointer;    } #ifdef Debug        pin_direction pindir;        Pout->querydirection (&pindir);        _asserte (Pindir = = pindir_output); #endif    //Find an input pin on the downstream filter.    Ipin *pin = 0;    HRESULT hr = Getunconnectedpin (pDest, Pindir_input, &pin);    if (FAILED (HR))    {        return hr;    }    Try to connect them.    hr = Pgraph->connect (POut, pIn);    Pin->release ();    return HR;}

function overloads for connectfilters of different parameters:

HRESULT connectfilters (    igraphbuilder *pgraph,     ibasefilter *psrc,     ibasefilter *pdest) {    if (pgraph = = NULL) | | (PSRC = = NULL) | | (PDest = = NULL))    {        return e_pointer;    }    The Find an output pin is on the first filter.    Ipin *pout = 0;    HRESULT hr = Getunconnectedpin (PSRC, Pindir_output, &pout);    if (FAILED (HR))     {        return hr;    }    hr = Connectfilters (pgraph, POut, pDest);    Pout->release ();    return HR;}
For example, now add an AVI Mux filter and a file Writer filter, and then connect them together. The code is as follows:
Ibasefilter *pmux, *pwrite;

hr = Addfilterbyclsid (pgraph, Clsid_avidest, L "AVI Mux", &pmux);

if (SUCCEEDED (HR))

{

hr = Addfilterbyclsid (pgraph, Clsid_filewriter, L "File Writer", &pwrite);

if (SUCCEEDED (HR))

{

hr = Connectfilters (pgraph, Pmux, pwrite);

Pwrite->release ();

}

Pmux->release ();

}


4. Find the interface on the filter and PIN


We need to enumerate all the filter in graph, or enumerate all the pins on the filter, one for the interface.

Find an interface implemented on the filter

HRESULT findfilterinterface (    igraphbuilder *pgraph,//Pointer to the Filter Graph Manager.    Refguid IID,           //IID of the interface to retrieve.    void **ppunk)          //Receives the interface pointer.{    if (!pgraph | |!ppunk) return e_pointer;    HRESULT hr = E_FAIL;    Ienumfilters *penum = NULL;    Ibasefilter *PF = NULL;    if (FAILED (Pgraph->enumfilters (&penum)))    {        return e_fail;    }    Query every filter for the interface.    while (S_OK = = Penum->next (1, &PF, 0))    {        hr = Pf->queryinterface (IID, ppunk);        Pf->release ();        if (SUCCEEDED (HR))        {break            ;        }    }    Penum->release ();    return HR;}

Finds an interface implemented on the pin of a given filter

HRESULT findpininterface (    ibasefilter *pfilter,  //Pointer to the filter to search.    Refguid IID,           //IID of the interface.    void **ppunk)          //Receives the interface pointer.{    if (!pfilter | |!ppunk) return e_pointer;    HRESULT hr = E_FAIL;    Ienumpins *penum = 0;    if (FAILED (Pfilter->enumpins (&penum)))    {        return e_fail;    }    Query every pin for the interface.    Ipin *ppin = 0;    while (S_OK = = Penum->next (1, &ppin, 0))    {        hr = Ppin->queryinterface (IID, ppunk);        Ppin->release ();        if (SUCCEEDED (HR))        {break            ;        }    }    Penum->release ();    return HR;}
Combined functions of two functions of Findfilterinterface and Findpininterfae

HRESULT findinterfaceanywhere (    igraphbuilder *pgraph,     refguid iid,     void **ppunk) {    if (!pgraph | |! Ppunk) return e_pointer;    HRESULT hr = E_FAIL;    Ienumfilters *penum = 0;    if (FAILED (Pgraph->enumfilters (&penum)))    {        return e_fail;    }    Loop through every filter in the graph.    Ibasefilter *PF = 0;    while (S_OK = = Penum->next (1, &PF, 0))    {        hr = Pf->queryinterface (IID, ppunk);        if (FAILED (HR))        {            //The filter does not expose the interface, but maybe            //one of its pins does.            hr = Findpininterface (PF, IID, ppunk);        }        Pf->release ();        if (SUCCEEDED (HR))        {break            ;        }    }    Penum->release ();    return HR;}

For example, through the Igraphbuilder::renderfile function, a playback link of AVI file containing DV format data is constructed. We want to get a DV video decoding filter on the Iipdvdec interface to set the DV decoding output to the image size of the original image of One-fourth, the code is as follows:
hr = Pgraph->renderfile (L "C:\\example.avi", 0);

if (SUCCEEDED (HR))

{

iipdvdec* Pdvdec;

hr = Findfilterinterface (Pgraph, Iid_iipdvdec, (void**) &pdvdec);

if (SUCCEEDED (HR))

{

........

}

}


5. Traverse the filter link

Given a filter on a filter link, we can get all the other filter up or down.

HRESULT Getnextfilter (Ibasefilter *pfilter,//Pointer to the starting filter pin_direction Dir,//DIRECTION to Search (upstream or downstream) Ibasefilter **ppnext)//receives a pointer to the next filter.    {if (!pfilter | |!ppnext) return e_pointer;    Ienumpins *penum = 0;    Ipin *ppin = 0;    HRESULT hr = Pfilter->enumpins (&penum);    if (FAILED (HR)) return HR;        while (S_OK = = Penum->next (1, &ppin, 0)) {//See if this pin matches the specified direction.        Pin_direction Thispindir;        hr = Ppin->querydirection (&thispindir);            if (FAILED (HR)) {//Something strange happened.            hr = e_unexpected;            Ppin->release ();        Break            } if (Thispindir = = Dir) {//Check if the pin is connected to another pin.            Ipin *ppinnext = 0;            hr = Ppin->connectedto (&ppinnext); if (SUCCEEDED (HR)) {// Get the filter that owns that pin.                Pin_info Pininfo;                hr = Ppinnext->querypininfo (&pininfo);                Ppinnext->release ();                Ppin->release ();                Penum->release (); if (FAILED (hr) | |                (Pininfo.pfilter = = NULL))                    {//Something strange happened.                return e_unexpected;                }//This is the filter we ' re looking for. *ppnext = Pininfo.pfilter;                Client must release.            return S_OK;    }} ppin->release ();    } penum->release ();    Did not find a matching filter. return E_FAIL;}







































Create a DirectShow application

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.