directshow教程(新整理)
DirectShow学习笔记
Filter Graph Manager
Filter Graph Manaer
ICaptureGraphBuilder2( Capture Filter Graph,
)
(1)SetFiltergraph // IGraphBuilder*, FilterGraph (2)RenderStream // Capture Source Filter PIN Capture ,Preview,CC,VBI, Filter Graph
Subtype
//MEDIASUBTYPE_Y
Formattype
FORMAT_None
FORMAT_DvInfo ( DV )
FORMAT_VideoInfo (
)
FORMAT_WaveFormatE (
)
FORMAT_VideoInfo2 ////
7.Filter
DirectShow Filter IFilterGraph::ConectDirect,IGraphBuilder::Connect
DirectShow
DirectShow
1 DirectShow
DirectShow
DirectDraw,DirectSound,Direct3D
Filter
DirectShow
2 Filter
Filter COM
,
PIN pin, PIN PIN . COM IPin
Filter PIN Filter
2 DirectShow
1
Filter Graph Manager
2
Filter Graph
3
Filter Graph Manager
IMediaControl
DirectShow开发环境搭建(整理)
DirectShow开发环境搭建(整理)directshow配置1. 下载安装 DirectX 9.0 SDK Update (February 2005) Extras。
2. 配置IDE环境中的include, lib路径 这步是为了以后更⽅便的做DSHOW开发,不⽤每次对每个⼯程都添加路径。
我的系统是32位win7+VS2010,需要到C:\Users\chef\AppData\Local\Microsoft\MSBuild\v4.0(chef是我的⽤户名)⽬录下修改er.props,这是⼀个XML⽂件,在节点IncludePath和LibraryPath分别添加上dshow sdk的include和lib路径就⾏了,不同路径间⽤分号隔离。
3. 编译baseclass 应该是对dshow的⼀个简单封装吧,据说⽤它开发⽐较⽅便。
到DirectX 9.0 SDK Update (February 2005) Extras\DirectShow\Samples\C++\DirectShow\BaseClasses下编译该⼯程。
貌似会出现⼀些for循环内定义变量的作⽤域、static定义变量省略了int类型等⼩问题,⼤家对照着错误提⽰修改⼀下就好了。
这⾥⽽外说⼀句,开源的东西拿过来⽤往往都会出现⼀些问题,这时不要⼼烦,不要急着到处问⼈,到处找⼈帮忙,应该积累看错误、改错误的经验,这也是初学者与有⼀定⼯作经验的程序员之间的⼀个显著区别吧。
4. 编译AMCap AMCap是⼀个通过摄像头采集视频并存成⽂件的⼯程,位置在DirectX 9.0 SDK Update (February 2005)Extras\DirectShow\Samples\C++\DirectShow\Capture\AMCap。
编译前先到项⽬属性的preprocessor definition中把WINVER、_WIN32_WINNT的值修改⼀下,这两个宏定义标志你使⽤的系统型号及版本, windows SDK中会根据这两个宏决定你是否能使⽤⼀些函数,我是改成0X0600了,之后应该就能成功编译了。
directshow配置总结
●dxtrans.h文件找不到(在qedit.h文件中包含dxtrans.h时出现的错误)solution:(1)这是VS2008里的在D:\Program Files\Microsoft Visual Studio 9.0搜索dxtrans.h复制到:\Program Files\Microsoft Visual Studio 9.0\VC\include(2) 或者在引用qedit.h 头文件的时候,加上这么几句:(此方法没有试验)#pragma include_alias( "dxtrans.h", "qedit.h" )#define __IDxtCompositor_INTERFACE_DEFINED__#define __IDxtAlphaSetter_INTERFACE_DEFINED__#define __IDxtJpeg_INTERFACE_DEFINED__#define __IDxtKey_INTERFACE_DEFINED__#include "Qedit.h"●error LNK2001: unresolved external symbol "void __stdcall FreeMediaType(struct _AMMediaType &)" (?FreeMe diaType@@YGXAAU_AMMediaType@@@Z)**.obj : error LNK2001: unresolved external symbol "void __stdcall FreeMediaType(struct_AMMediaType &)" (?FreeMediaType@@YGXAAU_AMMediaType@@@Z)**.obj : error LNK2001: unresolved external symbol "public: __thiscallCMediaType::~CMediaType(void)" (??1CMediaType@@QAE@XZ)**.obj : error LNK2001: unresolved external symbol "public: void __thiscallCMediaType::SetSubtype(struct _GUID const *)"(?SetSubtype@CMediaType@@QAEXPBU_GUID@@@Z)**.obj : error LNK2001: unresolved external symbol "public: void __thiscallCMediaType::SetType(struct _GUID const *)"(?SetType@CMediaType@@QAEXPBU_GUID@@@Z)**.obj : error LNK2001: unresolved external symbol "public: __thiscallCMediaType::CMediaType(void)" (??0CMediaType@@QAE@XZ)**.obj : error LNK2001: unresolved external symbol "int __stdcall lstrlenWInternal(unsigned short const *)" (?lstrlenWInternal@@YGHPBG@Z)编译DirectShow\Samples\C++\DirectShow\BaseClasses工程,并在自己的程序中链接生成的lib文件。
direct show
写这篇笔记,就当是对这个期间学习DirectShow的一个总结,假如它可以给你带来一些收获的话,那我会感到更高兴。
还有我遇到的一些问题,希望和大家一起讨论。
一、基本概念1.DirectShow概述DirectShow的主要功能是流媒体的采集与回放。
它集成了DirectDraw,DirectSound,Direct3D的一些技术。
它是一个开放的架构,你自己可以写自己的Filter组件。
DirectShow的架构:(这个图太经典了)2.FilterFilter其实就是一个COM组件,但它有自己的特性。
它由输入,处理,输出三部分组成,输入,输出是叫PIN,输入的叫输入pin,输出的叫输出PIN。
PIN也是一.种COM组件,它实现了IPin接口。
在Filter的实现里,PIN其实是Filter的一个数据成员。
(个人想法)(1)Filter分为三类:Source Filter(源过滤器),Transform Filter(转换过滤器)Render Filter(渲染过滤器)(2)Source Filter 的主要负责音、视频数据的采集,读取。
比如File SourceFilter(文件源过滤器),它是从磁盘里的音视文件读取数据的。
Transform Filter 负责音、视数据的压缩,解压,编码、解码、分析。
比如:Spliiter Filter(分离器),其功能是将音频流和视频流分离开来Mux Filter(复合器),将音频流和视频流全成单一数据流还有一此Encoder,Decoder,Compressor等。
(3)Render Filter负责音、视流的渲染,就是和输出,它将数据流送到输出设备,(显示器、磁盘、声卡)。
Filter有三种状态,运行,暂停,停止。
关于数据流:3.Filter Graph(过滤器图)Filter Graph是DirectShow一个基本的概念。
我们开发一个DirectShow应用,其中最重要的步骤就是构造一个FilterGraph。
DirectShow系统初级指南
DirectShow系统初级指南流媒体的处理,以其复杂性和技术性,一向广受工业界的关注。
特别伴随着因特网的普及,流媒体在网络上的广泛应用,怎样使流媒体的处理变得简单而富有成效逐渐成为了焦点问题。
选择一种合适的应用方案,事半功倍。
此时,微软的DirectShow,给了我们一个不错的选择。
DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与DirectX开发包一起发布。
目前,DirectX最新版本为8.1。
那么,DirectShow能够做些什么呢?且看,DirectShow为多媒体流的捕捉和回放提供了强有力的支持。
运用DirectShow,我们可以很方便地从支持WD M驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。
它广泛地支持各种媒体格式,包括Asf、Mpeg、Avi、Dv、Mp3、Wave等等,使得多媒体数据的回放变得轻而易举。
另外,DirectShow还集成了DirectX 其它部分(比如DirectDraw、DirectSound)的技术,直接支持DVD的播放,视频的非线性编辑,以及与数字摄像机的数据交换。
更值得一提的是,DirectSh ow提供的是一种开放式的开发环境,我们可以根据自己的需要定制自己的组件。
DirectShow使用一种叫FilterGraph的模型来管理整个数据流的处理过程;参与数据处理的各个功能模块叫做Filter;各个Filter在FilterGraph中按一定的顺序连接成一条“流水线”协同工作。
大家可以看到,按照功能来分,Filter大致分为三类:SourceFilters、TransformFilters和RenderingFilters。
SourceFilters主要负责取得数据,数据源可以是文件、因特网、或者计算机里的采集卡、数字摄像机等,然后将数据往下传输;TransformFitlers主要负责数据的格式转换、传输;RenderingFiltes主要负责数据的最终去向,我们可以将数据送给声卡、显卡进行多媒体的演示,也可以输出到文件进行存储。
DirectShow简易播放器实现指南
DirectShow简易播放器实现指南一、下载及安装DirectX9.0c版本已经将DirectShow分离出去了,下载时请选DirectX9.0b。
详细了解DirectShow性质介绍请看《DirectShow开发指南》一书。
1、使用VC向导生成一个具体项目;2、在VC的菜单中选择Project|Settings|C/C++,在弹出的对话框中的Category中选择Code generation,然后在Calling convention中选择_stdcall;使用多线程语言运行时库,然后在Use run-time library 中,Debug版选择Debug Multithreaded,Release版选择Multithreaded。
(我们学习中用的C++为Debug版)3、配置必要的链接库文件,即在VC的菜单中选择Project|Settings |Link,在弹出的对话框中的Category中选择General,然后在Object/library modules中输入如下代码:Debug版本strmbasd.lib, msvcrtd.lib, winmm.lib (本实验中还需要连接quartz.lib uuid.lib)Release版本strmbase.lib, msvcrt.lib, winmm.lib并且选中Ignore all default libraries。
说明:DirectShow SDK建议,DirectShow应用程序应该至少连接库文件strmiids.lib和quartz.lib。
前者定义了DirectShow标准的CLSID 和IID,后者定义了导出函数AMGetErrorText(如果应用程序中没有使用到这个函数,也可以不连接这个库)。
如果程序里包含了头文件streams.h,则一般库文件还要连接strmbasd.lib、uuid.lib、winmm.lib。
directshow学习笔记
定义自己的filter,实现编码和解码。
1.字符叠加Filter之功能分析总体需求:在视频流指定的一个时间段内叠加一段字符,要求能够做到实时叠加。
字符的内容、字体类型、大小、颜色、叠加的位置、存在的时间都能够定制,普遍支持RGB各种格式输入。
另外,除了支持静态字符叠加外,还要求支持其他效果的字符(包括滚动字幕,系统时间等)叠加,并且系统设计的扩展性良好。
功能单一化:字符叠加可以在一个filter中实现。
选择一种filter模型:这个filter同时有输入和输出(即在输入的视频帧上叠加完字符后再输出到下一级filter),因此我们的filter是一个Transform Filter。
由于输入和输出的媒体类型一致,而且输入和输出sample的数据大小不会变化,所以我们可以采用“就地”处理的transform Filter。
定义输入和输出我们的filter需要一个输入Pin和一个输出Pin,输入Pin支持的媒体类型有RGB32、RGB24、RGB565、RGB555等,并且输出Pin上的媒体类型与输入Pin保持一致。
接口定义接口方法应该包括设置字符的内容,设置字体的各种属性,选择字体的叠加效果,设置叠加位置,设置字符存在的时间段等。
其他一些特殊要求Filter处理的sample是一一对应的,而且内部不需要另外的使用线程。
这是一个标准的Transform Filter。
当我们要写一个source Filter,并且要将产生的数据“推”出去时,我们一般选择Csource,我们的Filter接收输入数据,经过一定的处理后要再输出数据,我们一般选择CtransformFilter (如果可以“就地”处理就选择CtransInPlaceFilter)。
如果我们的Filter同时有输入和输出,而且它的输入Pin上需要自己“拉”数据,则我们选择CbaseFilter,而在输入Pin上使用工具类CpullPin;当我们的Filter接收输入数据后不再需要输出,我们一般选择CbaseFilter。
wince下用DirectShow播放音频和视频
wince下用DirectShow播放音频和视频wince下用DirectShow播放音频和视频虽然网上关于wince下如何使用DirectShow播放多媒体文件的资料不多,但WinCE毕竟还属于windows,而桌面系统的DirectShow例子网上信手拈来,并且其中DirectShow的功能方法与之WinCE下差别不大,又本人实在没有信心比他们的轮子造得更为华丽,所以这篇文章就直接切入正题,不介绍DirectShow 的结构功能,直接来看看怎么用吧.(其实还是自己懒惰的原因大一些,恩,不过这个和本文的主题没多大关系:-)).为了方便代码的移植,所以我将DirectShow的操作封装成CMedia类,只要直接调用该类,就可以相当简便地调用DirectShow来播放多媒体文件了好,闲话至此,我们以具体代码看看是如何: //获取CMedia的实例CMedia *m_pMedia = CMedia::GetInstance();//设置播放的窗口m_pMedia->SetVideoWindow(hWnd);//打开媒体文件m_pMedia->Open(TEXT("A.AVI"));//播放m_pMedia->Play();...//播放结束后,调用Close释放资源m_pMedia->Open();没错,就是六行代码,就这么简单,可以顺利播放媒体文件.在这里要说一下的是,因为我们播放的是视频,需要有一个窗口显示,所以需要调用SetVideoWindow()函数来设置播放窗口.这个播放视频的窗口,可以是普通的窗口,也可以是Picture控件.当然咯,如果是播放音频文件,那么则完全可以无视这个函数.还有一个最值得注意的地方,当调用Open()成功之后,一定要调用Close()来释放资源,然后才能打开另一个媒体文件.否则,不释放的资源可能会导致很多莫名其妙的后果哦.等等,代码似乎还不完美,比如说,我想在文件播放之后再接着播放另外一个文件,那么我如何知道什么时候文件已经播放完毕了呢?这时候我们就需要请出SetNotifyWindow().该函数的作用是设置一个接受消息的窗口,当DirectShow有事件变更时,就会发送指定的消息到指定的窗口,原型如下:SetNotifyWindow(HWND hWnd, UINT wMsg,long lInstanceData)hWnd:接收消息的窗口句柄.wMsg:指定的自定义消息lInstanceData:消息的参数.那么,现在以接收一个视频播放结束事件的代码片段为例子: //自定义一个消息 #define WM_GRAPHNOTIFY (WM_USER + 13)//设置接收消息窗口和消息m_pMedia->SetVideoWindow(hWnd,WM_GRAPHNOTIFY,NULL);...//这个是消息循环函数LRESULT CMainWnd::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) ...{switch(wMsg)...{...case WM_GRAPHNOTIFY:...{LONG evCode,evParam1,evParam2;//获取此时的DirectShow事件if(m_pMedia->GetEvent(&evCode,&evParam1,&evParam2) == TRUE)...{if(evCode == EC_COMPLETE)...{MessageBox(NULL,TEXT("播放完毕"),TEXT(""),MB_OK);}}return 0;}}...}好了,知道播放完毕,就这么简单.恩,还很复杂..?呵呵,我觉得已经很简单了.文章的最后,让我们再来看看CMedia的其它几个有用的函数吧:CheckVisibility()描述:判断文件的种类当返回值为TRUE时,为视频文件;反之为只是音频文件.SetVolume(LONG lVolume, LONG lBalance)描述:设置音量.lVolume:设置音量的大小,范围为–10,000 到 0.lBalance:设置左右音量的均衡,范围是–10,000 到 10,000,默认是0.SetDisplayMode(DISPLAYMODE mode)描述:设置播放模式.DISP_FIT:按比例拉伸至视屏窗口.DISP_STRETCH:不按比例拉伸至视屏窗口.DISP_NATIVE:如果视频原本尺寸小于屏幕,则以原视频文件大小播放.否则,将和DISP_FIT相同 DISP_FULLSCREEN:全屏/**////////////////////////////////////////////////////////////////////////Media.h: interface for the CMedia class.////Version:// 1.2.0//Date:// 2007.05.08/**///////////////////////////////////////////////////////////////////////#ifndef MEDIA_H#define MEDIA_H#include <mmsystem.h>#include <streams.h>//--------------------------------------------------------------------//Macro define//The volume value#define MAX_VOLUME 0#define MIN_VOLUME -10000//The balance value#define MAX_BALANCE 10000#define MIN_BALANCE -10000//--------------------------------------------------------------------//Enum valueenum DISPLAYMODE...{//Fit to the play window size. How wide (height) the window is, how//is the move. Keep aspect ratio.DISP_FIT,//Stretch to the play window size. Don't keep the aspect ratio.DISP_STRETCH,//Full screen play.DISP_FULLSCREEN,//When the size of video is smaller than the play window, it displayes//as the video size. If it's bigger , it just like the DISP_FIT mode.DISP_NATIVE};//--------------------------------------------------------------------//The media file propertytypedef struct...{//The volume range is –10,000 to 0.//Divide by 100 to get equivalent decibel value (for example –10,000 = –100 dB).LONG lVolume;//The value from –10,000 to 10,000 indicating the stereo balance//As with the Volume property, units correspond to .01 decibels (multiplied by –1 when plBalance is a positive value).//For example, a value of 1000 indicates –10 dB on the right channel and –90 dB on the left channel.LONG lBalance;//Width of the videoLONG lWidth;//Height of the videoLONG lHeight;//Approximate bit rateLONG lBitRate;}MEDIAPROPERTY,*PMEDIAPROPERTY;//--------------------------------------------------------------------class CMedia...{public:BOOL GetEvent(LONG *plEvCode, LONG *plParam1, LONG *plParam2);BOOL SetNotifyWindow(HWND hWnd, UINT wMsg,long lInstanceData);BOOL SetVolume(LONG lVolume, LONG lBalance = 0);BOOL SetDisplayMode(DISPLAYMODE mode);BOOL GetMediaProperty(PMEDIAPROPERTY pOutProperty);static CMedia * GetInstance();void Close();BOOL CheckVisibility();void SetVideoWindow(HWND hWndVideo);BOOL Open(TCHAR * pszFileName);BOOL Stop();BOOL Pause();BOOL Play();virtual ~CMedia();protected:CMedia();// Collection of interfacesIGraphBuilder *m_pGB;IMediaControl *m_pMC;IMediaEventEx *m_pME;IVideoWindow *m_pVW;IBasicAudio *m_pBA;IBasicVideo *m_pBV;IMediaSeeking *m_pMS;TCHAR m_szFileName[MAX_PATH];HWND m_hWndVideo; //The window play videoHWND m_hWndNotify; //The window notifyBOOL m_bExitThrd;BOOL m_bThrdRunning;static CMedia * m_pInstance;DISPLAYMODE m_DispMode;};#endif //#ifndef MEDIA_H/**///////////////////////////////////////////////////////////////////////// Media.cpp: implementation of the CMedia class.///**///////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "Media.h"//----------------------------------------------------------------------------------------------//Macro define//Default play mode#define DEFAULT_DISPLAY_MODE DISP_NATIVE//----------------------------------------------------------------------//InitializeCMedia *CMedia::m_pInstance = NULL;//------------------------------------------------------------------------/**/////////////////////////////////////////////////////////////////////// // Construction/Destruction/**/////////////////////////////////////////////////////////////////////// CMedia::CMedia():m_pGB(NULL),m_pMC(NULL),m_pME(NULL),m_pVW(NULL),m_pBA(NULL),m_pBV(NULL),m_pMS(NULL),m_hWndVideo(NULL),m_bExitThrd(TRUE),m_bThrdRunning(FALSE),m_DispMode(DEFAULT_DISPLAY_MODE),m_hWndNotify(NULL)...{memset(m_szFileName,0,sizeof(m_szFileName));}CMedia::~CMedia()...{if(m_pInstance != NULL)...{delete m_pInstance;m_pInstance = NULL;}}//------------------------------------------------------------//Description:// Play the media file// When you call the function,you should call Open() before.////-------------------------------------------------------------BOOL CMedia::Play()...{// Run the graph to play the media fileif(m_pMC == NULL)...{return FALSE;}m_pMC->Run();return TRUE;}//------------------------------------------------------------//Description:// Pause.// When you call the function,you should call Open() before.////-------------------------------------------------------------BOOL CMedia::Pause()...{if(m_pMC == NULL)...{return FALSE;}m_pMC->Pause();return TRUE;}//------------------------------------------------------------//Description:// Stop.// When you call the function,you should call Open() before.////-------------------------------------------------------------BOOL CMedia::Stop()...{if(m_pMC == NULL || m_pMS == NULL)...{return FALSE;}m_pMC->Stop();m_pMS->SetPositions(0, AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning);return TRUE;}//--------------------------------------------------------------------------//Description:// Open the media file. When succeed in calling the function ,//you should call the Close() to release the resource////-------------------------------------------------------------------------BOOL CMedia::Open(TCHAR *pszFileName)...{BOOL bResult = FALSE;if(_tcslen(pszFileName) >= MAX_PATH)...{goto END;}else...{_tcscpy(m_szFileName,pszFileName);//Check the file existingHANDLE hdFile =CreateFile(m_szFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);if(hdFile == INVALID_HANDLE_VALUE)...{//The file doesn't existgoto END;}else...{CloseHandle(hdFile);}}// Initialize COMif(CoInitializeEx(NULL, COINIT_MULTITHREADED) != S_OK)...{goto END;}// Get the interface for DirectShow's GraphBuilderif(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB) != S_OK)...{goto END;}// Have the graph construct its the appropriate graph automaticallyif(m_pGB->RenderFile(m_szFileName, NULL) != NOERROR)...{goto END;}// QueryInterface for DirectShow interfacesif(m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC) != NOERROR)...{goto END;}if(m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&m_pME) != NOERROR)...{goto END;}if(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&m_pMS) != NOERROR)...{goto END;}// Query for video interfaces, which may not be relevant for audio filesif(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW) != NOERROR)...{goto END;}if(m_pGB->QueryInterface(IID_IBasicVideo, (void **)&m_pBV) != NOERROR)...{goto END;}// Query for audio interfaces, which may not be relevant for video-only files if(m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA) != NOERROR)...{goto END;}// Is this an audio-only file (no video component)?if (CheckVisibility() == TRUE)...{if(m_pVW->put_Owner((OAHWND)m_hWndVideo) != NOERROR)...{goto END;}if(m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN) != NOERROR) ...{goto END;}}//Set play modeSetDisplayMode(m_DispMode);bResult = TRUE;END:if(bResult == FALSE)...{//Release the resourceClose();}return bResult;}//------------------------------------------------------------//Description:// This method sets an owning parent for the video window.////Parameters:// hWnd : [in] Handle of new owner window.////----------------------------------------------------------void CMedia::SetVideoWindow(HWND hWndVideo)...{m_hWndVideo = hWndVideo;}//------------------------------------------------------------//Description:// Check the file visibility// When you call the function,you should call Open() before.////Parameters:// TRUE: Video// FALSE: It's not the video////------------------------------------------------------------BOOL CMedia::CheckVisibility()...{if (!m_pVW)...{//No VideoWindow interface. Assuming audio/MIDI file or unsupported video codec return FALSE;}if (!m_pBV)...{//No BasicVideo interface. Assuming audio/MIDI file or unsupported video codec. return FALSE;}// If this is an audio-only clip, get_Visible() won't work.//// Also, if this video is encoded with an unsupported codec,// we won't see any video, although the audio will work if it is// of a supported format.long lVisible;if(m_pVW->get_Visible(&lVisible) != NOERROR)...{return FALSE;}return TRUE;}//------------------------------------------------------------//Description:// Release the resource which opened in the Open()////------------------------------------------------------------void CMedia::Close()...{// Relinquish ownership (IMPORTANT!) after hidingif(m_pVW)...{m_pVW->put_Visible(OAFALSE);m_pVW->put_Owner(NULL);}if(m_pMC != NULL)...{m_pMC->Release();m_pMC = NULL;}if(m_pME != NULL)...{m_pME->SetNotifyWindow(NULL,NULL,NULL); m_pME->Release();m_pME = NULL;}if(m_pMS != NULL)...{m_pMS->Release();m_pMS = NULL;}if(m_pBV != NULL)...{m_pBV->Release();m_pBV = NULL;}if(m_pBA != NULL)...{m_pBA->Release();m_pBA = NULL;}if(m_pVW != NULL)...{m_pVW->Release();m_pVW = NULL;}if(m_pGB != NULL)...{m_pGB->Release();m_pGB = NULL;}// Finished with COMmemset(m_szFileName,0,sizeof(m_szFileName));CoUninitialize();}//------------------------------------------------------------ //Description:// Get the instance of object////------------------------------------------------------------ CMedia * CMedia::GetInstance()...{if(m_pInstance == NULL)...{m_pInstance = new CMedia();}return m_pInstance;}//------------------------------------------------------------ //Description:// Get the media file property.// When you call the function,you should call Open() before. ////------------------------------------------------------------ BOOL CMedia::GetMediaProperty(PMEDIAPROPERTY pOutProperty) ...{MEDIAPROPERTY prop = ...{0};if(m_pBA == NULL || m_pBV == NULL)...{return FALSE;}//Get the audio propertym_pBA->get_Volume(&prop.lVolume);m_pBA->get_Balance(&prop.lBalance);//Get the video propertyif(CheckVisibility() == TRUE)...{m_pBV->get_BitRate(&prop.lBitRate);m_pBV->GetVideoSize(&prop.lWidth,&prop.lHeight);}*pOutProperty = prop;return TRUE;}//------------------------------------------------------------//Description:// Set the display mode.// When you call the function,you should call Open() before.////------------------------------------------------------------BOOL CMedia::SetDisplayMode(DISPLAYMODE mode)...{if(m_pVW == NULL)...{return FALSE;}m_DispMode = mode;if(mode == DISP_FULLSCREEN)...{m_pVW->put_FullScreenMode(OATRUE);}else...{//Restore to the normal modem_pVW->put_FullScreenMode(OAFALSE);RECT rcWnd = ...{0};GetClientRect(m_hWndVideo,&rcWnd);LONG lWndWidth = rcWnd.right - rcWnd.left;LONG lWndHeight = rcWnd.bottom - rcWnd.top;MEDIAPROPERTY prop = ...{0};GetMediaProperty(&prop);if(mode == DISP_FIT || mode == DISP_NATIVE)...{LONG lDispLeft,lDispTop,lDispWidth,lDispHeight;if(mode == DISP_NATIVE && lWndWidth >= prop.lWidth && lWndHeight >= prop.lHeight) ...{lDispLeft = (lWndWidth - prop.lWidth) / 2;lDispTop = (lWndHeight - prop.lHeight) / 2;lDispWidth = prop.lWidth;lDispHeight = prop.lHeight;}else...{if(prop.lWidth * lWndHeight > lWndWidth * prop.lHeight)...{lDispWidth = lWndWidth;lDispHeight = (LONG)((float)lDispWidth / (float)prop.lWidth * prop.lHeight); lDispLeft = 0;lDispTop = (lWndHeight - lDispHeight) / 2;}else if(prop.lWidth * lWndHeight < lWndWidth * prop.lHeight)...{lDispHeight = lWndHeight;lDispWidth = (LONG)((float)lDispHeight / (float)prop.lHeight * prop.lWidth); lDispLeft = (lWndWidth - lDispWidth) / 2;lDispTop = 0;}else...{lDispWidth = lWndWidth;lDispHeight = lWndHeight;lDispLeft = 0;lDispTop = 0;}}m_pVW->put_Left(lDispLeft);m_pVW->put_Top(lDispTop);m_pVW->put_Width(lDispWidth);m_pVW->put_Height(lDispHeight);}else if(mode == DISP_STRETCH)...{m_pVW->put_Left(0);m_pVW->put_Top(0);m_pVW->put_Width(lWndWidth);m_pVW->put_Height(lWndHeight);}}return TRUE;}//------------------------------------------------------------//Description:// Set the volume.// When you call the function,you should call Open() before.////Parameters:// lVolume:[in] The volume (amplitude) of the audio signal.// Range is –10,000 to 0.// lBalance:[in] The balance for the audio signal. Default value is 0.// The value from –10,000 to 10,000 indicating the stereo balance.////------------------------------------------------------------BOOL CMedia::SetVolume(LONG lVolume, LONG lBalance)...{if(m_pBA == NULL)...{return FALSE;}if(lVolume < MIN_VOLUME && lVolume > MAX_VOLUME && lBalance < MIN_BALANCE && lBalance > MAX_BALANCE)...{return FALSE;}m_pBA->put_Volume(lVolume);m_pBA->put_Balance(lBalance);return TRUE;}//----------------------------------------------------------------------//Description:// Registers a window that will handle messages when a specified event occurs.////Parameters:// hWnd:[in] Handle of window to notify. Pass NULL to stop notification.// wMsg:[in] Window message to be passed as the notification.// lInstanceData:[in] Value (instance data) to be passed as the lParam parameter for the lMsg message.////-----------------------------------------------------------------------------BOOL CMedia::SetNotifyWindow(HWND hWnd, UINT wMsg,long lInstanceData)...{if(m_pME == NULL)...{return FALSE;}m_pME->SetNotifyWindow((OAHWND)hWnd,wMsg,lInstanceData);return TRUE;}//---------------------------------------------------------------------- //Description:// This method retrieves the notification event.////----------------------------------------------------------------------- BOOL CMedia::GetEvent(LONG *plEvCode, LONG *plParam1, LONG *plParam2) ...{if(m_pME == NULL)...{return FALSE;}LONG evCode, evParam1, evParam2;if(m_pME->GetEvent(&evCode, &evParam1, &evParam2, 0) == NOERROR)...{*plEvCode = evCode;*plParam1 = evParam1;*plParam2 = evParam2;// Spin through the eventsm_pME->FreeEventParams(evCode, evParam1, evParam2);}else...{return FALSE;}return TRUE;}本文来自CSDN博客,转载请标明出处:/norains/archive/2007/05/14/1609118.aspx。
directshow教程(新整理)
Directshow教程0.11MSDN翻译系列作者:黄丁杰说明:如果有任何问题请联系din-je@。
是本人业余翻译的如果有错误请直接发到我邮箱我会立刻改正,directshow的其他文章我会在以后不断翻译出来。
如果觉得好请帮我作作宣传。
欢迎转载,但是禁止修改。
Directshow起步。
本章主要介绍diirectshow在编写程序时所需的基本概念。
在本章你可以总揽下directshow 技术。
你必须在总体上对本章的编程和媒体有所了解。
本章将介绍。
设置编译环境。
介绍directshow应用程序编程。
如何播放一个文件设置编译环境:你可以编译工程在命令行模式下或者在vs集成环境中头文件所有的directshow应用程序都使用下面的头文件。
Dshow。
H部分directshow接口需要附加的头文件。
这些文件会在接口的注意中给出。
所需的库文件directshow需要如下的库文件strmiidl。
Lib 该库包含CLSIDs和IIDs的接口。
所有的directshow都需要该库。
Quartz。
Lib 该库包含AMGetErrorText函数。
如果你没有调用该函数,该库没有用。
记住在你的编译环境中必须把directx SDK 的头文件库和连接库的目录作为vs优先搜索的路径。
这样可以保证编译的时候用的是最新版本的文件。
介绍directshow应用程序编程本章介绍编写一个directshow程序的基本技术和概念,读完本章你就可以写个你自己的directshow的应用程序了。
滤镜和图像滤镜directshow是由被称作滤镜的东西构成的。
滤镜是一个软件包用来执行对多媒体流的一些操作。
比如directshow的滤镜可以读出一个文件从视频捕捉设备获取视频流解码各种各样的多媒体格式,比如MPEG-1S视频。
传输视频和音频到屏幕和声卡。
滤镜几乎完成视频播放所需要的从输入到输出的所有功能。
比如一个MPEG-1的滤镜。
它可以输入MPEG码流然后输出图像帧用于后续显示在directshow程序中只要执行把滤镜连接在一起就可以了。
DirectShow插件使用手册
DirectShow插件使用手册【摘要】本文档介绍了DirectShow连接相机时的插件使用,通过本套插件可连接海康的工业相机。
一、环境配置1.相机环境配置打开MVS,若PC与相机不在同一网段,则配置IP,设置好相机参数。
确保相机能在MVS上正常取流。
2.注册和注销插件在客户端MVS安装完成后,不会默认注册此插件,需要用户手动用管理员权限运行register.bat脚本注册此插件,插件脚本存放在Development\ThirdPartyPlatformAdapter\DirectShow文件夹内。
可用graphedt.exe程序查看是否注册成功,插件注册在Video Capture Source项内,如图1。
图1用管理员权限运行unregister.bat文件可注销已注册的DShow插件。
3.环境检测(1)在graphedt.exe程序中打开菜单Graph-Insert Filters…;(2)在Video Capture Source项内选择MvCamera DirectShow Source;(3)选中MvCamera DirectShow Source并右键打开Filter Properties…进行相机选择和参数获取和设置等操作,如图2;(4)在DirectShow Filters中选择Video Renderer,并将Video Out与Input相连接,如图3;(5)菜单Graph-Play进行预览;图2 属性页图3 连接页二、参考示例提供DirectShowDisplay示例程序供用户参考,对示例做简要介绍:DirectShowDisplay示例为控制台程序,路径为Development\Samples\DirectShow\DirectShowDisplay,支持Render播放。
在头文件MvDSSource.h内列出相机列表获取、参数获取、参数设置等接口供外部调用。
此示例程序可编译x86和x64版本,分别对应插件的x86和x64版本。
DirectShow编程指南
IMediaPosition *pimp;
hr = pigb->QueryInterface(&IID_IMediaPosition, (void **)&pimp);
hr = pimp->put_CurrentPosition(0);
然而,用IMediaPosition只能用seek时间,如果你用 IMediaSeeking接口,你能用多种格式seek,用100呐秒单位,frame(帧),字节,media samples,或者是interlaced video fields。你可以用IMediaSeeking::SetTimeFormat 设置你需要的格式。注意,确信你不在播放媒体文件,当你设置格式的时候。
HRESULT hr;
LONG evCode;
LONG evParam1;
LONG evParam2;
其中ghApp是一个graph产生的事件的响应窗口句柄。ghInst是窗口的HINSTANCE。evCode将保存事件代码,evParam1和evParam2保存事件的参数。
实例化一个filter graph manager。
hr = CoCreateInstance(CLSID_FilterGraph,
NULL,
CLSCTX_INPROC_SERVER,
IMediaSeeking *pims;
hr = pigb->QueryInterface(IID_IMediaSeeking, (void **)&pims);
#define HELPER_RELEASE(x) { if (x) x->Release(); x = NULL; }
DirectShow使用大全
DirectShow使用大全一.使用directshow时应该添加lib文件Strmiids.lib、Quartz.lib 、Strmbase.lib 具体添加那个见下面的说明Header FilesAll DirectShow applications use the Dshow.h header file. Some DirectShow interfaces require additional header files. These requirements are noted in the interface reference.Library FilesThe following table shows the library files DirectShow uses.Library file DescriptionQuartz.lib Exports the AMGetErrorText function. If you do not call this function, this library is not required.Strmbase.lib If you do not use the DirectShow base classes, this library is not required. For information about the difference between Strmbase.lib and Qtzbase.lib, see Building DirectShow Filters Strmiids.lib Exports class identifiers (CLSIDs) and interface identifiers (IIDs). All DirectShow applications require this library.In your build environment, the SDK Include and Lib directories should be the first directories in the search path. This ensures that you are using the most recent versions of these files.二DirectShow初探可能到现在为止,还没有哪个玩过游戏的人没有接触过Microsoft的DirectX 的。
DirectShow入门如何利用CaptureGraphBuilder构建Graph图表
DirectShow入门如何利用CaptureGraphBuilder构建Graph图表Capture Graph Builder可以用来构建大多数的filter图表,并不仅仅是捕捉graph。
本文简单介绍了如何利用Capture Graph Builder 来构建graph。
Capture Graph Builder暴露了ICaptureGraphBuilder2接口指针,首先创建一个capture builder,和一个filter图表管理器对象,然后用图表管理器对象指针初始化Capture Graph Builder。
代码如下:连接filterICaptureGraphBuilder2::RenderStream方法可以同时将两个或者三个filter连接成一个链(chain)。
通常情况下,当每个filter只有一个输出pin和一个输入pin时,这个方法就才,适用。
我们现在先忽略前两个参数,第三个参数是一个IUnknown指针,指向一个filter或者输出pin。
第五,六个参数指向IBaseFilter指针。
RenderStream就将三个filter连接成一个链。
例如,假设A,B,C 是三个filter,每个filter只有一个输出pin和一个输入pin。
下面的代码可以将B连接到A上,将B连接到C上。
所有的连接都是智能化的,如果是将两个filter相连,你可以将中间的参数设置为NULL:也可以调用两次这个函数创建一个更长的链条。
如果最后的一个参数设置为NULL,这个方法就自动的为graph 设置一个renderer filter。
如果是视频就设置成Video Renderer,如果是音频就设置为DirectSoundRenderer。
因此RenderStream(NULL, NULL, A, NULL, NULL)等价于RenderStream(NULL, NULL, A, NULL, R)这里R指的是Render Filter。
最新DirectShow视频采集开发指南
卡,为 CLSID_VideoCompressorCategory,表示枚举系统中的视频压缩器。下面的代码演示了如何枚 举系统中的视频捕捉卡。 //枚举视频设备 ICreateDevEnum *pDevEnum = NULL; CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc); pMoniker->Release(); break; } pClassEnum->Release(); 而下面的代码则用于判断系统中是否安装了指定的视频压缩器。 ICreateDevEnum *pDevEnum = NULL; CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&pDevEnum); IEnumMoniker *pClassEnum = NULL; //列举视频压缩设备 pDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pClassEnum, 0); while (pClassEnum->Next(1, &pMoniker, &cFetched) == S_OK) { IPropertyBag* pProp= NULL;
directshow的中文资料之设备列举和捕捉接口
directshow的中文资料之设备列举和捕捉接口第一篇:directshow的中文资料之设备列举和捕捉接口directshow的中文资料之设备列举和捕捉接口这篇解释和示例如何通过DirectShow的接口去初始化和访问系统的硬件设备。
代表性的,DirectShow应用程序使用下面类型的硬件。
音/视频捕捉卡音频或视频回放卡音频或视频压缩或解压卡(象MPEG解码器)下面将以AV设备作参考。
如何列举设备包括在DirectShow SDK中的接口,类,和例子提供了音/视频捕捉和回放的功能。
因为文件源过滤器和filter graph manager处理了内在的工作,所有,添加捕捉功能到一个应用程序中,只需添加很少的代码。
你可以通过列举系统硬件设备和得到设备列表完成特别的任务(例如:所有的视频捕捉卡的列表)。
DirectShow自动为win32和Video for Windows 设备实例化过滤器。
要AV设备工作,首先,你必须检测当前系统存在的设备。
ICreateDevEnum接口建立指定类型的列表。
提供你需要的检测和设置硬件的功能。
访问一个指定的设备有三步,详细的说明和代码如下:建立系统硬件设备的列表首先,申明一个列表指针,然后通过CoCreateInstance 建立。
CLSID_SystemDeviceEnum是我们想建立对象的类型,IID_ICreateDevEnum是接口的GUID。
ICreateDevEnum *pCreateDevEnum;CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,(void**)&pCreate DevEnum);其次,建立一个特别类型的硬件设备的列表(例如视频捕捉卡)申明一个IEnumMoniker接口,并把他传给ICreateDevEnum::CreateClassEnumerator 方法。
DirectShow开发指南——学习笔记
第一部分DirectShow基础知识第1章系统概述1.1DirectX 大家族1.DirectX软件开发包是微软公司提供的一套在Wdinows操作平台上开发高性能图形、声音、输入、输出和网络游戏的编程接口。
2.DirectShow是DirectX中的一位集大成者。
1.2DirectShow简介一、DirectShow系统1.图中最大的一块是DriectShow系统,虚线以下是Ring0特权级别的硬件设备,虚线以上是Ring3特权级别的应用层。
DirectShow位于应用层中。
2.它使用一种叫作Filter Graph的模型来管理整个数据流的处理过程;参与数据处理的各个功能模块叫作Filter;各个Filter在Filter Graph中按一定的顺序连接成一条流水线协同工作。
3.Filter大致分为3类:(1)Source Filters 负责获取数据,文件源可以是文件等,然后将数据往下传输。
(2)Transform Filters负责数据的格式转换,将数据继续往下传输。
(3)Rendering Filters负责数据的最终去向,将数据送给显卡、声卡进行多媒体的演示,或者输出到文件进行存储。
二、播放第一个媒体文件问题。
本身是一种规范,而不是实现。
当使用C++实现时,COM组件就是一个C++类,而接口就是纯虚类。
规范规定,任何组件或接口都必须从IUnknown接口中继承而来。
IUnknown定义了3个重要函数:(1)QueryInterface负责组件对象上的接口查询(2)AddRef增加引用计数(3)Release用于减少引用计数组件实际上是一个C++类,对于组件的外部使用者来说,这个类名一般不可知。
COM规范规定,每个组件都必须实现一个与之相对应的类工作Class Factory。
类工厂也是一个COM组件,它实现了IClassFactory接口。
在IClassFactory接口函数CreateInstance中,才能使用new操作生成一个COM组件实例。
DirectShow学习指南之数据流结束通知 net 电脑资料
DirectShow学习指南之数据流完毕通知 net 电脑资料当一个源filter完毕发送数据流时,它调用和它连接的filter的输入pin的IPin::EndOfStream,然后下游的filter再依次通知与之相连的filter,当一个源filter完毕发送数据流时,它调用和它连接的filter的输入pin的IPin::EndOfStream,然后下游的filter再依次通知与之相连的filter。
当EndOfStream方法一直调用到rendererfilter的时候,最后的一个filter就给filter图表管理器发送一个ECPLETE事件通知。
如果renderer有多个输入pin,当所有的输入pin都接收到end of stream通知的时候,它才会给filter图表管理器发送一个ECPLETE事件通知。
Filter必须在其他函数调用之后调用EndOfStream函数,比方IMemInputPin::Receive.。
在一些情况下,下游的filter可能比源filter更早的发现数据流的完毕。
在这种情况下,下游filter发送完毕stream的通知,同时, IMemInputPin::Receive函数返回SFALSE直到图表管理器停顿。
这个返回值提示源filter停顿发送数据。
对ECPLETE事件的缺省处理缺省的情况下,filter图表管理器并不将ECPLETE事件通知发送给应用程序,当所有的数据流都发送了ECPLETE事件通知后,它才给应用程序发送一个ECPLETE事件通知。
所以,应用程序只有在所有的数据流停顿的时候才能接收到这个通知。
filter图表管理器通过计算支持seeking接口的filter,并且具有一个renderer pin,没有相应的输出pin,就可以确定数据流的数目。
Filter图表管理器通过下面的方法来决定一个pin是否是个renderer 。
1、pin的IPin::QueryInternalConnections方法通过nPin参数返回0;在拉模式下的数据流完毕通知在IAsyncReader连接中,源filter并不发送数据流完毕的通知,相应的发送数据流完毕的通知是有renderer filter发出的。
directshow
directshow 使⽤⼿记(6)directshow ⾥⾯包含有两种特使的filter ⼀种是DMO ⼀种是ACM或ICM 他们和普通的filter⽤法有⼀些差别,你会发现在graphedit的枚举列表中他们的显⽰的颜⾊和普通的filter也是区别的,dmo是绿⾊的,acm是蓝⾊的。
⽽且还看不到这些dmo注册的位置。
这⾥是从其他地⽅摘抄过来的,英⽂的,凑合看应该能看的懂,我都能看的懂,您应该没多⼤问题。
Using DMO In DirectShowEnables Application to use a Directx Media Object(DMO) in a filter graph,The ‘DMO Wrapper’ exposes this interface.To add a DMO to filter graph,You should create an instance dmo wrapper filter and query it for the IDMOWrapperFilter interface. Then call the IDMOWrapperFilter::Init() method to initialize the filter with the dmoUsing :HRESULT Hr;IBaseFilter *pFilter;Hr = CoCreateInstance(CLSID_DMOWrapperFilter,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void **)&pFilter);If(SUCCEEED(Hr)){IDMOWrapperFilter *pWrap;Hr=pFilter->QueryInterface(IID_IDMOWrapperFilter,(void **)&pWrap);If(SUCCEED(Hr)){Hr=pWrap->Init(dmoid,dmocategoryid)pWrap->Release();}}Note: dmoid is the dmo object’s GUID and the dmocategoryid is the dmo’s CateGory’s GUIDRequirements:Include Dmodshow.h. Link to Dmoguids.lib.Other people’s DMO, We can’t get them’s GUID ,Category and MediaType,what we can do for us ?havn’t ways! No,we should enum all DMO if you don’t you the dmo’s category, There are some common categorys in directshow system. them will help you,may be.If you really don’t know this, when you use the function ‘EnumDMO()’ the first parameter you should set GUID_NULL for it.For details about the EumDMO function ,see the Microsoft ‘s web msdn or the directx sdk document. After get the GUID,you may validate in regedit.DMO Category DirectShow EquivalentDMOCATEGORY_AUDIO_ENCODER CLSID_AudioCompressorCategoryDMOCATEGORY_AUDIO_DECODER CLSID_LegacyAmFilterCategoryDMOCATEGORY_VIDEO_ENCODER CLSID_VideoCompressorCategoryDMOCATEGORY_VIDEO_DECODER CLSID_LegacyAmFilterCategoryUsing:IEnumDMO* pEnum = NULL;HRESULT hr = DMOEnum(category, // CategoryDMO_ENUMF_INCLUDE_KEYED, // Included keyed DMOs0, NULL, // Input types (don't care)0, NULL, // Output types (don't care)&pEnum);if (SUCCEEDED(hr)){CLSID clsidDMO;WCHAR* wszName;do{hr = pEnum->Next(1, &clsidDMO, &wszName, NULL);if (hr == S_OK){// Now wszName holds the friendly name of the DMO, // and clsidDMO holds the CLSID.if(!strcmp((char *)wszName,Name)){return TRUE;}// Remember to release wszName!CoTaskMemFree(wszName);}} while (hr == S_OK);pEnum->Release();}。
DirectShow设置亮度、对比度等属性
DirectShow设置亮度、对比度等属性DirectShow设置亮度、对比度等属性分类:DirectShow2008-04-10 10:47 534人阅读评论(0) 收藏举报在DirectShow,对很多设置可以通过IAMVideoProcAmp接口设置亮度、对比度等属性下面m_pVideo是源设备Filter,IAMVideoProcAmp *pProcAmp = 0;hr = m_pVideo->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp); if(SUCCEEDED(hr)){long Min, Max, Step, Default, Flags, Val;// 亮度.if( g_Brightness > 0 ){hr = pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step, &Default, &Flags);if(SUCCEEDED(hr)){hr = pProcAmp->Get(VideoProcAmp_Brightness, &Val, &Flags);Val = Min+(Max-Min)*g_Brightness/100;pProcAmp->Set(VideoProcAmp_Brightness, Val, Flags);}}//对比度if( g_Contrast > 0 ){hr = pProcAmp->GetRange(VideoProcAmp_Contrast, &Min,&Max, &Step,&Default, &Flags);if(SUCCEEDED(hr)){hr = pProcAmp->Get(VideoProcAmp_Contrast, &Val, &Flags);Val = Min+(Max-Min)*g_Contrast/100;pProcAmp->Set(VideoProcAmp_Contrast, Val, Flags);}}//饱和度if( g_Saturation > 0 ){hr = pProcAmp->GetRange(VideoProcAmp_Saturation, &Min, &Max, &Step, &Default, &Flags);if(SUCCEEDED(hr)){hr = pProcAmp->Get(VideoProcAmp_Saturation, &Val, &Flags);Val = Min+(Max-Min)*g_Saturation/100;pProcAmp->Set(VideoProcAmp_Saturation, Val, Flags);}}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Directshow教程0.11MSDN翻译系列作者:黄丁杰说明:如果有任何问题请联系din-je@。
是本人业余翻译的如果有错误请直接发到我邮箱我会立刻改正,directshow的其他文章我会在以后不断翻译出来。
如果觉得好请帮我作作宣传。
欢迎转载,但是禁止修改。
Directshow起步。
本章主要介绍diirectshow在编写程序时所需的基本概念。
在本章你可以总揽下directshow 技术。
你必须在总体上对本章的编程和媒体有所了解。
本章将介绍。
设置编译环境。
介绍directshow应用程序编程。
如何播放一个文件设置编译环境:你可以编译工程在命令行模式下或者在vs集成环境中头文件所有的directshow应用程序都使用下面的头文件。
Dshow。
H部分directshow接口需要附加的头文件。
这些文件会在接口的注意中给出。
所需的库文件directshow需要如下的库文件strmiidl。
Lib 该库包含CLSIDs和IIDs的接口。
所有的directshow都需要该库。
Quartz。
Lib 该库包含AMGetErrorText函数。
如果你没有调用该函数,该库没有用。
记住在你的编译环境中必须把directx SDK 的头文件库和连接库的目录作为vs优先搜索的路径。
这样可以保证编译的时候用的是最新版本的文件。
介绍directshow应用程序编程本章介绍编写一个directshow程序的基本技术和概念,读完本章你就可以写个你自己的directshow的应用程序了。
滤镜和图像滤镜directshow是由被称作滤镜的东西构成的。
滤镜是一个软件包用来执行对多媒体流的一些操作。
比如directshow的滤镜可以读出一个文件从视频捕捉设备获取视频流解码各种各样的多媒体格式,比如MPEG-1S视频。
传输视频和音频到屏幕和声卡。
滤镜几乎完成视频播放所需要的从输入到输出的所有功能。
比如一个MPEG-1的滤镜。
它可以输入MPEG码流然后输出图像帧用于后续显示在directshow程序中只要执行把滤镜连接在一起就可以了。
就是把一个滤镜的输入和另外一个滤镜的输出连接在一起就可以了。
一组连接在一起的滤镜叫做图像滤镜。
比如下面的图示就是一个播放A VI文件的图像滤镜的例子正如上面图示的,文件滤镜把A VI文件从硬盘读入。
A VI分离滤镜分离文件流为两个数据流。
一个是视频压缩流,一个是硬盘流。
A VI解压滤镜用于解压视频流生成视频帧。
视频显示滤镜用于把视频帧用directdraw或者GDI显示到屏幕上。
音频留输入到默认声音设备滤镜把声音通过directsound播放出来。
因此应用程序就不用管理任何数据流。
代替的,滤镜被叫做高端组件叫做图像滤镜的进行控制。
程序只要创建一些高级API。
就像RUN(用于在图像控件中移动数据)或者STOP(用于停止数据流)。
但是如果你要求更多的数据流控制,那你也可以直接存取控制的COM接口。
图像滤镜也会反馈一定的事件消息给应用程序。
图像滤镜可以服务另外的目的。
提供给应用程序创建图像滤镜的方法,还有把各个滤镜连接在一起的方法。
(directshow同时也提供一些帮助的组件可以简单的处理。
这些全部都有在文档中描述。
编写一个directshow程序总的来说,写个directshow程序必须进行这三个步骤。
就像下面的图例。
1.创建个图像滤镜管理的实例2.然后用图像理解管理实例建立一个图像滤镜。
外部滤镜间依赖于这个图像滤镜。
3.应用程序应用图像滤镜控制图像滤镜和数字流在滤镜中的流动。
通过这些处理。
应用程序也应该回应滤镜管理事件。
当处理结束后。
应用程序释放图像滤镜管理器和所有的滤镜。
因为directshow是基于COM 的,因此图像滤镜管理和滤镜都是COM对象。
因此你必须对COM客户端编程有所了解。
具体的可以在DirectX SDK中的一篇文章叫做《Using COM》中有很好的介绍COM对象的资料。
而且是有很多COM编程的书籍可以参考。
如何播放一个文件本文章是想让你喜欢上Directshwo编程。
我们要创建一个简单的命令行下的程序用于播放音频或者视频文件,这个程序实在是太简单了,可是它所完成的功能却是非常强大。
这个程序只要短短的几行的代码就可以搞定了。
可是它所完成的功能却是以前只有专门公司才能开发出来的软件所能实现的。
它可以用来演示播放任何的多媒体文件。
用它你可以立刻喜欢上directshow的编程。
就像上面的文章说描述的那样,一个directshow应用程序总是有三个基本的步骤。
1.建立个图像滤镜管理器的实例2.用图像滤镜管理建立一个图像滤镜3.给它运行的消息,让数据流在各个滤镜中移动。
好了,我们开始编写我们直接的多媒体演示程序。
首先我们必须调用CoInitialize来初始化COM库。
(记住directshow在编程的时候全部都没有传统编写COM的影子,因此初学者很容易被它的假象所欺骗,以为directshow根本就不是COM的,或者认为COM就是那么简单。
其实directshow就有点象MFC,通过c+++的封装技术和其他大量的技术把COM技术的很多细节都隐藏其来。
其实在背后微软已经为我们写了很多很多的代码。
我们应该感谢微软为我们作的一切,但是我们也应该佩服微软。
居然可以把代码的复用技术发挥到如此的境界。
这些是我们国内软件企业所要学习的地方。
废话了)HRESULT hr = CoInitialize(NULL);if (FAILED(hr)){// Add error-handling code here. (Omitted for clarity.)}为了保持程序的简单,这个例子忽略了返回值。
但是你必须在你自己编写的代码中始终检查从任何方法中返回的HERSULT值。
这个是很重要的因为他可能是空值。
那在后续的调用的时候将产生很多莫名其妙的错误。
问题严重哦。
接下来,我们调用CoCreateInstance用来建立滤镜管理器IGraphBuilder *pGraph;HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);如上所示,传入的第一个参数类的标识是CLSID_FilterGraph。
按照字面的意思就是用于创建图像滤镜。
返回我们就得到了一个HERSULT了,这个是指向滤镜的一个句柄。
这个东西就是一个图像滤镜了,它将来要用到所有其他的后续处理之中。
还有那个执行描述参数传入的是CLSCTX_INPROC_SERVER。
Directshow支持释放线程模型。
所以你可以调用CoinitializeEx函数用COINIT_MULTITHREADED参数。
该函数还返回了个IgraphBuilder接口。
该接口包含了大多数的用于构建图像滤镜的方法。
还用两个方法被用于这个例子。
ImediaControl接口,该接口用于控制数据流。
可以用来停止和启动数据流。
ImediaEvent接口,该接口用于获取图像滤镜的的事件。
在这个例子中我们用来等待播放结束。
这两个滤镜都是从图像滤镜引出来的。
我们可以用刚才返回的IgraphBuilder来得到他们。
下面是范例。
IMediaControl *pControl;IMediaEvent *pEvent;hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);接下来你就可以建立个图像滤镜。
用来播放文件。
可是这也是很简单的调用hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);IgrapBuilder::RenderFile方法可以用来播放特定的文件。
第一次参数就是文件名,不过必须是UNICODE的。
第二个参数是用来保留的,现在只要填NULL就可以了。
当然了,如果输入的文件名有错误,或者是根本就不认识的格式,它就会返回错误。
这个时候就应该通过一些错误的代码来报告错误。
因为这个例子只是简单的例子,因此没有这些代码,我们始终假设文件是存在的,并且格式是可以被解码的。
要是代用成功图像滤镜就会准备播放了。
现在我们可以调用ImediaControl::Run函数让他运行。
hr = pControl->Run();一旦调用成功,数据就开始在滤镜中移动。
并且将其播放出来。
播放是在另外的线程后台进行的。
我们只要等待它播放结束就可以了。
我们可以调用ImediaEvent::WaitForCompletion 还等待播放结束。
long evCode = 0;pEvent->WaitForCompletion(INFINITE, &evCode);该方法会一直等待知道播放解说或者播放出错返回。
那个参数INFINITE是告诉该函数,我要等待直到播放结束才返回。
不过还有其他的参数,可以方便的使用可以参考Responding to Events这篇文章。
当应用程序结束就可以释放这些接口的指针用于关闭.COM库pControl->Release();pEvent->Release();pGraph->Release();CoUninitialize();下面是完整的代码,真的很少。
#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();}关于directshow本章将介绍directshow的整体架构。