1、简单地播放文件 DIRECTSHOW 为了在程序中使用DirectShow,我单独安装DirectX版本为9.0。在安装DirectX之后,程序中需要引用“dshow.h”头文件,并导入“Strmiids.lib”库文件和“quartz.lib”库文件才可以使用DirectShow。代码如下: #include <dshow.h> #pragma comment (lib,"quartz.lib")
DirectShow主要由过滤器(Filter Graph)图表构成。通常需要设计一个过滤图表(Filter Graph),向过滤图表中添加相应的过滤器,最后连接过滤器的引脚就完成了功能的设计。过滤图表中包含了各种Filter,这些Filter能够按一定顺序连接在一起,构成一条流水线。从功能的角度划分,Filter大体可以分为3类,Source Filters、Transform Filters和Rendering Filters。 Source Filters主要负责获取数据,可以是一个文件、一个采集卡、声卡或数码相机等。 Transform Filters负责数据的转换、传输。例如各种编码器、解码器等。 Rendering Filters负责数据的最终去向,例如将数据传送到声卡、显卡或存储为文件。 我采用是DSHOW的filter,在建好filter graph后,调用buider()然后在相应窗口上render这个数据. 1. direct show的常用编程接口 |
CLSCTX_INPROC_SERVER
客户希望创建在同一进程中运行的组件。为能够同客户在同一进程中运行,组建必须是在DLL中实现的。
CLSCTX_INPROC_HANDLER
客户希望创建进程中处理器。一个进程甲处理器实际上是一个只实现了某个组件一部分的进程中组件。该组件的其他部分将由本地或
远程服务器上的某个进程外组件实现。
CLSCTX_LOCAL_SERVER
客户希望创建一个在同一机器上的另外一个进程中运行的组件。本地服务器是由EXE实现的。
//snap picture
long bitmapSize = 0;
if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, 0)))
{
unsigned char * buffer = new unsigned char[bitmapSize];
if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, (long *)buffer)))
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)buffer;
int nColors = 0;
if( lpbi->biBitCount <=8)
nColors = 1 << lpbi->biBitCount;
hdr.bfType = ((WORD) ('M' << 8) | 'B'); //always is "BM"
hdr.bfSize = bitmapSize + sizeof( hdr );
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD) (sizeof(BITMAPFILEHEADER) + lpbi->biSize +
nColors * sizeof(RGBQUAD));
CFile bitmapFile(m_MixPic, CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
bitmapFile.Write(&hdr, sizeof(BITMAPFILEHEADER));
bitmapFile.Write(buffer, bitmapSize);
bitmapFile.Close();
}
delete [] buffer;
}
CLSCTX_REMOTE_SERVER
客户希望创建一个在远程机器上运行的组件。此标志需要分布式COM正常工作。
第四个参数iid为组件上待使用的接口的IID。CoCreateInstance将在最后一个参数中返回此接口的指针。
通过将一个IID传给CoCreateInstance,客户将无需在创建组件之后去调用其QueryInterface函数。
传给CoCreateInstance的最后两个参数同传给QueryInterface的参数是一样的。
4. DSHOW中怎样将视频绑定到指定的窗口或控件上
主要分以下几个方面说明:
The Video Window 视频窗口;
Using the IVideoWindow Interface;
DirectShow Sample Code 代码;
The Video Window 视频窗口;
当你渲染一个视频时,filter graph 将包含一个视频渲染的filter。视频渲染即将其渲染到屏幕上的一个窗口内。除非特别指定,
不然视频回放窗口是一个顶层窗口,并且有自己的边框和工具条。指定方法是使渲染视频的窗口作为你程序窗口的一个子窗口。
这可以由设置视频窗口的属性来达到目的,指定其父窗口、风格、和位置。
视频渲染filter支持IVideoWindow接口,该接口包含了设置和获取视频窗口的属性的方法。然而,如果你用filter graph manager
构造了自己的filter graph,你不一定持有指向视频renderer 过滤器的指针,因此 filter graph manager也支持IVideoWindow。
它持有一个filter graph中所有filter所暴露的IVideoWindow的列表。当你通过filter graph manager调用一个IVideoWindow方法时,
filter graph manager将会把调用分发到那些filter上。这样,filter graph manager能支持单个filter上的操作,而不用程序去找出
适当的filter。
filter graph manager使用了同样的机制暴露了IBasicVideo和IBasicAudio接口。这些接口包含了设置音频和视频属性的方法。
通过过滤图管理器调用这些方法,而不要通过单个filter调用。
Using the IVideoWindow Interface;
首先,创建一个filter graph manager的实例并构造一个filter graph。
然后,在渲染之前,设置视频窗口的属性,如下:
邦定视频到一个指定的父窗口。通过调用IVideoWindow::put_Owner方法,传递一个指向父窗口的指针给它。
IVideoWindow *pVidWin = NULL;
pGraph->QueryInterface(IID_IVideoWindow,(void **)&pVidWin);
pVidWin->put_Owner((OAHWND)g_hwnd);
通过调用IVideoWindow::put_WindowStyle方法,并传递一个风格组合参数,就可以将视频窗口改变为子窗口。
WS_CHILD标志表示窗口是一个子窗口;WS_CLIPSBLINGS标志防止了窗口在另一个子窗口的客户区绘制。
pVidWin->put_WindowStyle(WS_CHILD|WS_CLIPSBLINGS);
通过调用IVideoWindow::SetWindowPosition 方法,可以设置视频窗口的位置。这个方法采用设备坐标
口的x,y,宽度、高度。同样的程序延展了视频窗口并填充了整个父窗口。
CRECT grc;
GetClientRect(g_hwnd,&grc);
pVidWin->SetWindowPosition(rect.left, rect.top, rect.Width(),