1)directshow初识(2009.12.05)
创建DirectShow应用程序步骤:
第一步,首先,需要调用CoInitialize来作初始化,然后调用CoCreateInstance创建Filter Graph Manager:
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
return;
}
IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
类标识符(CLSID)是CLSID_FilterGraph。Filter Graph Manager由进程内DLL(in-process DLL)提供,因此参数3,dwClsContext的值为CLSCTX_INPROC_SERVER。由于DirectShow运行自由线程模式(free-threading model),所以你同样可以使用COINIT_MULTITHREADED参数来调用CoInitializeEx
PS:HRESULT 是一种简单的数据类型,通常被属性和 ATL 用作返回值。
下表说明各种不同的值。头文件 winerror.h 中包含更多的值。
名称 说明 值
S_OK 操作成功 0x00000000
E_UNEXPECTED 意外的失败 0x8000FFFF
E_NOTIMPL 未实现 0x80004001
E_OUTOFMEMORY 未能分配所需的内存 0x8007000E
E_INVALIDARG 一个或多个参数无效 0x80070057
E_NOINTERFACE 不支持此接口 0x80004002
E_POINTER 无效指针 0x80004003
E_HANDLE 无效句柄 0x80070006
E_ABORT 操作已中止 0x80004004
E_FAIL 未指定的失败 0x80004005
E_ACCESSDENIED 一般的访问被拒绝错误 0x80070005
不能简单地把返回值与 S_OK 和 S_FALSE 比较,而要用 SUCCEEDED 和 FAILED 宏进行判断。
第二步,创建filter graph
调用CoCreateInstance得到的IGraphBuilder接口包含了大部分创建filter graph的方法。在这个例子中还需要另外两个接口:IMediaControl和IMediaEvent。IMediaControl控制数据流,它包含开启和停止graph的方法;IMediaEvent包含从Filter Graph Manager获取事件的方法,在这个例子中,这个接口用来得到回放结束事件。所有这些接口由Filter Graph Manager提供,使用得到的IGraphBuiler接口指针来查询得到。
IMediaControl *pControl;
IMediaEvent *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
第三步,创建filter graph
对于文件回放只需要一个简单的调用:
hr = pGraph->RenderFile(L"C://Example.avi", NULL);
IGraphBuilder::RenderFile方法创建了一个能够播放指定文件的filter graph,事实上,原本需要做的一些如创建filter实例及将这些filter连接起来的工作,都由这个方法自动完成了,如果是视频文件,这个filter graph看起来应该是这个样子:
[file source]->[如果是缩格式,这里是个解码器]->[Video Renderer]
要开始回放,调用IMediaControl::Run方法:
hr = pControl->Run();
当filter graph运行时,数据经过各个filter最后回放为视频或音频。回放发生在一个单独的线程中。你可以通过调用IMediaEvent::WaitForCompletion方法来等待回放的结束:
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
上面这个方法在播放期间被阻塞,直至播放结束或超时。
当应用程序结束时,需要释放接口指针并关闭COM库:
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
创建简单的directshow播放程序过程的完整代码如下所示:
#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();
}
PS:
1.这里所使用的fiter graph manag构建graph filter采用igraphbuilder::renderfile方法构建一个完成的文件回放graph
2.该程序只支持.avi格式视频播放,只有播放直至结束的回放功能。
二 VS2005 C++ 项目添加“依赖”、“库目录”和“包含目录”2009-12-08
1. 添加编译所需要(依赖)的 lib 文件
“项目->属性->配置属性->连接器->输入->附加依赖项”里填写“winsock.lib”,多个 lib 以空格隔开。
(等同于“#pragma comment(lib, "winsock.lib") ”语句)
2. 添加库(Libs)文件目录
方法 1“项目->属性->配置属性->连接器->常规->附加库目录”
方法 2:[菜单]“工具->选项->项目和解决方案->C++ 目录”,选择对应平台,然后添加所需“库文件”目录
3. 添加包含(include)文件目录
方法 1:[解决方案资源管理器]“项目->属性->配置属性->C/C++->常规->附加包含目录”
方法 2:[菜单]“工具->选项->项目和解决方案->C++ 目录”,选择对应平台,然后添加所需“包括文件”目录