DirectShow在DirectX9 3D上的纹理播放
作者:Kagula
日期:2009-3-30
环境:
[1] Microsoft DirectX SDK (November 2008)
[2] Windows SDK_6.0.6001.18000.367
[3]Visual Studio 2005
读者对象:
[1]掌握DirectX 9 GRAPH基础知识
[2]熟悉DXUT和C++语言编程
[3]计算机专业英语基础
[4]了解COM(非必须的)
内容概述:
根据Windows SDK中,DirectShow 3D纹理播放的例子,做一次学习总结。正文部份内容直接copy自Microsoft的英文文档,建议英语不好的人慎入。
这里关注的是DXUT(Direct3D)中使用DirectShow的问题。
现在的DirectShow已经被Microsoft移到了Windows SDK中。
正文:
第一部份:介绍DirectShow
下图是DirectShow播放AVI的原理。
图一DirectShow播放原理图
The Video Renderer filter (即上图中的Video Renderer) draws the frames to the display, using DirectDraw or GDI. The Default DirectSound Device filter plays the audio stream, using DirectSound
图二 DirectShow编程模式图
图二,从左到右是每个DirectShow应用程序都要经历的步骤:
第一步:
建立Filter Graph Manager实例。
第二步:
Building a filter graph。
第三步:
The application uses the Filter Graph Manager to control the filter graph and stream data through the filters. Throughout this process, the application will also respond to events from the Filter Graph Manager。
图二中,从Step2开始底部的那些小框框就是Filter(过滤器)。
数据就像一条水流,经过一个个过滤器处理,最后被还原成Frame交给DirectDraw或GDI。
现在可以看下Microsoft DirectShow 9.0中的例子“How To Play a File”,加深概念上的认识。
第二部份:Prepare, DXUT中封装DirectShow
如果你对上面这个例子已经熟悉,打开下面的文件夹
你的Win SDK安装目录/Microsoft SDKs/Windows/v6.1/
Samples/Multimedia/DirectShow/Players/Texture3D9
现在我们可以看一下Texture3D9这个例子。它把AVI文件的每一帧,放在纹理上,实现在纹理上播放AVI文件。我对它进行了剥离使之能够和我现有的DirectX9(DXUT)融合,事实上证明在DXUT中使用DirectShow来实现纹理播放是很容易的。
在对DirectShow初始化的时候,设置了回调类,使得3D上的纹理坐标和纹理能够被及时刷新。
我把DirectShow的调用封装在了C3DAVIShow这个类中,而回调函数被放在CTextureRender这个Class中,同时使用了CLock类,防止纹理对象的读取冲突。
第三部份:Let’s do it
让我们首先建立C3DAVIShow这个Class.
下面是C3DAVIShow.h的部份代码
C3DAVIShow.h
// 这里省略若干行代码
class C3DAVIShow:public CDX9Obj // CDX9Obj是个抽象类,仅定义接口标准。
{
// 这里省略若干行代码
//应用程序准备退出,时调用,当用户退出程序,OnPrepareAppExit会被调用,其次再调用OnLostDevice,其次再调用OnDestroyDevice
void OnPrepareAppExit();
// UpgradeGeometry用来更新几何体的纹理坐标,我这里的几体体是由两个三角形组成的一个平面。
HRESULT UpgradeGeometry(LONG lActualW, LONG lTextureW,LONG lActualH, LONG lTextureH );
// InitDShowTextureRenderer用来初始化DirectShow
HRESULT InitDShowTextureRenderer();
// 这里省略若干行代码
public:
LPDIRECT3DVERTEXBUFFER9 m_pVB; // Buffer to hold vertices
LPDIRECT3DTEXTURE9 m_pTexture; // Our texture
D3DFORMAT m_TextureFormat;
// 下面是DirectShow用到的对象,这里不是必须得使用static,已经写成这样就懒得改了。
static SmartPtr<IGraphBuilder> m_pGB; // GraphBuilder
static SmartPtr<IMediaControl> m_pMC; // Media Control