[DirectShow] 002 - How To Play a File

As the article Introduction to DirectShow Application Programming describes, a DirectShow application always performs the same basic steps:

1.     Create an instance of the Filter Graph Manager .

2.     Use the Filter Graph Manager to build a filter graph.

3.     Run the graph, causing data to move through the filters.

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

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

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

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

Start by calling CoInitialize to initialize the COM library

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

 

HRESULT hr = CoInitialize(NULL);

if (FAILED(hr))

{

    // Add error-handling code here. (Omitted for clarity.)

}

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

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

Next, call CoCreateInstance to create the Filter Graph Manager:

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

 

IGraphBuilder *pGraph;

HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,

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

 

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

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

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

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

·         IMediaEvent has methods for getting events from the Filter Graph Manager. In this 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 is done 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 the file format is not recognized. Assuming that the method succeeds, however, the filter 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 is rendered as video and audio. Playback occurs on a separate thread. You can wait for playback to complete by calling the IMediaEvent::WaitForCompletion method:

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

long evCode = 0;

pEvent->WaitForCompletion(INFINITE, &evCode);

 

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

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

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

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

pControl->Release();

pEvent->Release();

pGraph->Release();

CoUninitialize();

Here is the complete code for the example described in this article:

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

 

 

#include <dshow.h>

void main(void)

{

    IGraphBuilder *pGraph = NULL;

    IMediaControl *pControl = NULL;

    IMediaEvent   *pEvent = NULL;

 

    // Initialize the COM library.

    HRESULT hr = CoInitialize(NULL);

    if (FAILED(hr))

    {

        printf("ERROR - Could not initialize COM library");

        return;

    }

 

    // Create the filter graph manager and query for interfaces.

    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,

                         IID_IGraphBuilder, (void **)&pGraph);

    if (FAILED(hr))

    {

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

        return;

    }

 

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

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

 

    // Build the graph. IMPORTANT: Change this string 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 a real application, because it

            // can block indefinitely.

        }

    }

    pControl->Release();

    pEvent->Release();

    pGraph->Release();

    CoUninitialize();

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值