[DirectShow] 002 - How To Play a File

来源:互联网 发布:叶启田心情无人知 编辑:程序博客网 时间:2024/04/27 23:38

As the article Introduction to DirectShowApplication Programming describes, a DirectShowapplication always performs the same basic steps:

1.    Create an instance of the Filter Graph Manager.

2.    Use the Filter Graph Manager tobuild a filter graph.

3.    Run the graph, causing data tomove through the filters.

就像Introduction toDirectShow Application Programming文章描述的,一个DirectShow应用程序总是执行以下相同的基本步骤:

1.      创建一个Filter Graph Manage实例。

2.      使用Filter Graph Manager生成Filter Graph.

3.      运行Graph,让数据在Filters中移动。

Start bycalling CoInitialize to initialize the COM library

从调用CoInitialize初始化COM库开始:

 

HRESULThr = CoInitialize(NULL);

if(FAILED(hr))

{

    // Add error-handling code here. (Omittedfor clarity.)

}

To keep things simple, this example ignores the return value, butyou should always check the HRESULT value from any method call.

为使事情简单,上面代码忽略了返回值。但是你需要检查其他函数返回的HRESULT值。

Next, call CoCreateInstance to create the Filter GraphManager:

接下来,调用CoCreateInstance创建Filter Graph Manager.

 

IGraphBuilder*pGraph;

HRESULThr = CoCreateInstance(CLSID_FilterGraph, NULL,

CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void **)&pGraph);

 

As shown, the class identifier (CLSID) is CLSID_FilterGraph. TheFilter Graph Manager is provided by an in-process DLL, so the execution contextis CLSCTX_INPROC_SERVER. DirectShow supports the free-threading model, so youcan also call CoInitializeEx with the COINIT_MULTITHREADED flag.

Class Identifier(CLSID)CLSID_FilterGraphFilter Graph Manager由一个进程内dll提供,所以执行环境是CLSCTX_INPROC_SERVERDirectShow支持自由线程类型,所以可以在调用CoInitializeEx的时候设置COINIT_MULTITHREADED标记。

The call to CoCreateInstance returns the IGraphBuilder interface, which mostly contains methods for building the filtergraph. Two other interfaces are needed for this example:

·        IMediaControl controls streaming. It contains methods for stopping and startingthe graph.

·        IMediaEvent has methods for getting events from the Filter Graph Manager. Inthis example, the interface is used to wait for playback to complete.

调用CoCreateInstance获得IGraphBuilder接口,这个接口包含了大部分生成filter graph的方法。在这个例子中还使用到了两个接口:

IMediaControl 控制媒体流,这个接口包含开始和停止Graph方法。

IMediaEvent 这个接口有从Filter Graph Manager获得事件的函数,在这个例子中,这个接口被用来等待回放结束。

Both of these interfaces are exposed by the Filter Graph Manager.Use the returned IGraphBuilder pointer to query for them:

IMediaControl*pControl;

IMediaEvent   *pEvent;

hr= pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

hr= pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

这两个接口都由Filter Graph Manager暴露。使用IGraphBuilder的指针询问这两个接口指针。

Now you can build the filter graph. For file playback, this isdone by a single method call:

现在可以生成Filter Graph了,调用一个简单的方法就可以回放文件:

hr= pGraph->RenderFile(L"C://Example.avi", NULL);

The IGraphBuilder::RenderFile method builds a filter graph that can play the specified file.The first parameter is the file name, represented as a wide character (2-byte)string. The second parameter is reserved and must equal NULL.

IGraphBuilder::RenderFile方法生成的Filter Graph可以播放指定的文件。第一个参数是以宽字符串呈现的文件名,第二个参数是保留参数必须为NULL

This method can fail if the specified file does not exist, or thefile format is not recognized. Assuming that the method succeeds, however, thefilter graph is now ready for playback. To run the graph, call the IMediaControl::Run method:

当指定的文件不存在或者格式不正确,这个函数会返回失败。如果返回成功,那么filter graph就准备好回放了。调用IMediaControl::Run方法运行这个graph

hr= pControl->Run();

When the filter graph runs, data moves through the filters and isrendered as video and audio. Playback occurs on a separate thread. You can waitfor playback to complete by calling the IMediaEvent::WaitForCompletion method:

filter graph运行的时候,数据在filters之间穿行,并且以视频和音频的形式呈现。回放发生在分离线程。可以调用IMediaEvent::WaitForCompletion方法等待回放结束:

longevCode = 0;

pEvent->WaitForCompletion(INFINITE,&evCode);

 

This method blocks until the file is done playing, or until thespecified time-out interval elapses. The value INFINITE means the applicationblocks indefinitely until the file is done playing. For a more realisticexample of event handling, see Responding to Events.

这个函数阻塞,直到文件播放完成,或者指定的超时时间到达。INFINITE值意味着应用程序无限期的阻塞,知道文件播放完成。更多事件句柄的例子,参考Responding to Events

When the application is finished, release the interface pointersand close the COM library:

当应用程序结束的时候,释放接口指针,关闭COM库:

pControl->Release();

pEvent->Release();

pGraph->Release();

CoUninitialize();

Here is the complete code for the example described in thisarticle:

下面是这个例子的完整代码:

 

 

#include<dshow.h>

voidmain(void)

{

    IGraphBuilder *pGraph = NULL;

    IMediaControl *pControl = NULL;

    IMediaEvent   *pEvent = NULL;

 

    // Initialize the COM library.

    HRESULT hr = CoInitialize(NULL);

    if (FAILED(hr))

    {

        printf("ERROR - Could notinitialize COM library");

        return;

    }

 

    // Create the filter graph manager andquery for interfaces.

    hr = CoCreateInstance(CLSID_FilterGraph,NULL, CLSCTX_INPROC_SERVER,

                        IID_IGraphBuilder, (void**)&pGraph);

    if (FAILED(hr))

    {

        printf("ERROR - Could not createthe Filter Graph Manager.");

        return;

    }

 

    hr =pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);

    hr = pGraph->QueryInterface(IID_IMediaEvent,(void **)&pEvent);

 

    // Build the graph. IMPORTANT: Change thisstring to a file on your system.

    hr =pGraph->RenderFile(L"C://Example.avi", NULL);

    if (SUCCEEDED(hr))

    {

        // Run the graph.

        hr = pControl->Run();

        if (SUCCEEDED(hr))

        {

            // Wait for completion.

            long evCode;

           pEvent->WaitForCompletion(INFINITE, &evCode);

 

            // Note: Do not use INFINITE in areal application, because it

            // can block indefinitely.

        }

    }

    pControl->Release();

    pEvent->Release();

    pGraph->Release();

    CoUninitialize();

}

 

 

原创粉丝点击