利用DirectShow实现视频文件播放
基于DirectShow的客户端实时视频流回放技术

d, t ) e r lr  ̄ fe 等。过滤器通过向文件读写、 ei 修改数据和显示数据到输 出设备上来操作流媒体。为了完成整个 任务 。 必须要将所有的过滤器 F t 连接起来 , 3 ir l e 这 种过滤器组成了过滤器图表结构 , 如图 I 所示。
Die th w r cS o
术, 避开了复杂的视频流解压算法 , 具有较好的通用性和可移植性。
1 Drc hw 简 介 i t o eS
M ic hw的设计 目 SD eSo rt 标是: 隔离数据传输 、 硬件兼容、 流同步等底层处理, 使客户能够轻轻松松地创建 W n w 应用平台上的多媒体应用程序[。它对媒体数据的处理采用流媒体( uie a t ) i os d ¨ M l d 咖 的方式, t is m 在应用 中大大的减少了编程的复杂程度, 同时又可以自 动协商从数据源到应用的转换 , 口 流接 提供了统一的、 可以预测 的数据存取的控制方法, 这样应用程序在播放媒体数据时不需要考虑它最初的来源和格式。
V I 2 . o. 8N 1 o
Ma .2 o r 06
基 于 Drc hw的客户 端 i to eS 实 时视频 流 回放 技 术
刘 琼 , 慧灿 周
( 湖南文理学院 计算机科学系 。 湖南 常德 450 ) 103
摘
要: 介绍 了Dr t o 术的原理并 以 M E i c hw技 eS P G一1视频流解 码回放为例 , 详细说 明了 Ft Gah的构建 与实现方法。 ir r l e p 文献标识码 : A 文章编号 :6 1 2 120 )1 0 1 3 17 —03 (060 —06 —0
维普资讯
在过滤器图表结构中, 源过滤器用来从数据源劳敢数据 , 并将数据传送到过滤器 图表中, 这里的数据
基于Directshow的H.264网络视频监控客户端实现

基于Directshow的H.264网络视频监控客户端实现彭锋;林和志;黄联芬【摘要】In order to realize the real-time broadcasting of H. 264 at video monitoring client, a method that combines Directshow with MFC is adopted. Directshow taken as a drive of the video player receives data from the network, performs cache, decoding and display, and provides the API for MFC, which is used to design UI to control the process of playing. After verification on PC, the player can smoothly play the H. 264 video stream received from network, and the packet loss rate islow. The innovation of this paper is to use Directshow to play smoothly real-time H. 264 stream received from network.%为了实现视频监控客户端对H.264实时播放,采用Directshow与MFC相结合的方法,用Directshow作为视频播放的驱动,从网络接收数据,完成缓存,解码显示及封装成MFC可调用的API,MFC用来设计户界面,对播放过程进行相应的控制,达到了播放从网络接收到的H.264视频的目的.经过PC机上验证,可以流畅地从网络上接收播放H.264视频流,并且丢包率很小.在此用Directshow来实时流畅的播放从网络上接收到的H.264视频流.【期刊名称】《现代电子技术》【年(卷),期】2011(034)008【总页数】3页(P118-120)【关键词】H.264;Directshow;MFC;网络视频监控【作者】彭锋;林和志;黄联芬【作者单位】厦门大学,福建,厦门,361005;厦门大学,福建,厦门,361005;厦门大学,福建,厦门,361005【正文语种】中文【中图分类】TN919-340 引言视频监控以其直观方便信息内容丰富而广泛应用于安保,监控等场合,成为商业,交通,住宅等领域防范的重要手段。
基于DirectShow的MPEG-4监控系统的设计与实现

Drc 软件 开发包是微软公 司提供 的一套 在 i t eX Wi o s n w 操作平 台上开发高性能图形、声音 、输入 、 d 输 出和网络游戏 的编程接 口。Dic 是众多技术的 rt eX 集合, 其中的Drc h w i t o 技术为在Wi o s eS n w 平台上处 d 理各种格式的媒体文件的回放 、音视频采集等高性 能的 多媒 体应用 ,提 供完整 的解决方 案 【 1 l。 ‘ 6
Ab ta t A e a da v c dDi cS o tc n lg o lme i p l ain d v lp n rsn e . sr c n w n d a e r th w h oo yf r n e e mut daa p i to e eo me ti pe e td i c S T i tc oo S a p id i ewo k d dgtlv d o mo i r g s se b s d o Ⅳ【EG- .M ut e i hs e h lg i p l n a n t r e ii ie nt i y tm a e n n y e a on E ) 4 l m i da p o e s g i e l e i Di cS o fa eicu ig c pu i g d c d g pa ig b c , s e ig ec T i r c si s rai d n n z r t h w rm , ld a tr , e o i , l n a k e k t. hs e n n n n y n
DirectShow视频采集方案

流媒体处理技术以其复杂性和技术性一直受到人们的关注。随着网络技术的不断发展,流媒体在网络上得到了广泛地应用。如何能够简单、有效地进行流媒体处理,已成为一个焦点问题。为此,Microsoft推出了DirectShow,DirectShow是Microsoft推出的基于Windows平台的流媒体处理开发包,它与DirectX一起发布。DirectShow对流媒体的捕捉、回放提供了强大的支持,使用它还可以在基于WDM驱动的采集卡上进行数据捕捉。本节将介绍有关DirectShow的相关知识。
while (pEnumPins->Next(1,&pOutpin,NULL)==S_OK)
{
pOutpin->QueryDirection(&pDir);
if (pDir==dir)
{
return pOutpin;
}
}
return 0;
}
用户可以按下面的方式获得某个过滤器的输入、输出引脚。
IPin * pComOut,*pComIn ;
在开发DirectShow应用程序时,通常需要设计一个过滤图表(Filter Graph),向过滤图表中添加相应的过滤器,最后连接过滤器的引脚就完成了功能的设计。例如,实现一个简单的视频预览功能,需要向过滤图表中添加一个视频捕捉源过滤器和一个Video Renderer过滤器,将视频捕捉源过滤器的输出引脚与Video Renderer过滤器的输入引脚相连就可以了。而在程序中只需要按照设计过滤图表的捕捉添加过滤器并连接过滤器引脚就可以了。在连接过滤器引脚时需要注意:只能是输出过滤器引脚与输入过滤器引脚相连,两个输出过滤器或两个输入过滤器引脚是不能相连的。
为了在程序中使用DirectShow,需要单独安装DirectX,当前DirectX的最新版本为9.0,即DirectX9.0,用户可以从Microsoft的官方网站上免费下载。在安装DirectX之后,程序中需要引用“dshow.h”头文件,并导入“Strmiids.lib”库文件和“quartz.lib”库文件才可以使用DirectShow。代码如下:
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的H.264流媒体播放器设计

命令控 制等 ; 其二就是客户端对接收到 的多媒体流实 时解 码 后播 放的技 术 。显然 , 网络 通信 可 以使 用 wn o ssce 技 i w ok t d 术 , 媒 体 流 的解 码 播 放 可 以使 用 dr t o 多 i es w技 术 。本 文 采 e h 用 dr t o i cs w应 用 框 架 , 计 了 网 络 源 ftr h 2 解 码 e h 设 i e 和 .6 l 4 ie 并 ft , 通过 Fl r rp lr ie ah构建 了流媒体播放器 J t G 。
1 D rc h w技术 和 H.6 i to es 2 4视频 压 缩标 准简 介
Dr t o i cs w是微软公 司提供的一套流媒体开发软件包 , e h 为 在 wno s 台 上处 理 各 种格 式 的媒 体 文件 的 回放 、 视 频 采 idw 平 音 集的高性能要求的多媒体应用 , 了完整的解决方案 。。 提供 Dre hw是一套完 全基 于 C M 的应用 系统 , i to es O 该系统位 于 应 用 层 中 , 使 用 Fl r rp 它 ie ah的 模 型 来 管 理 整 个 数 据 流 t G 的 处 理 过 程 ; 与 数 据 处 理 的 各 个 功 能 模 块 叫 Fl r各 个 参 ie ; t Fl r Fl rG ah中按 照 一定 的顺 序连 接成 一 条 “ 水 ie 在 ie rp t t 流 线” 同工作 。Flr 协 ie 是一个 C M 组件 , 功能可 以 由用 户 t O 其 自行 实 现 , i c hwS K 电为 用 户 提 供 了一 些 标 准 的 Fl r D r t o D eS ie t 供 用 户 使 用 。各 个 Fl r FlrG ah中按 一 定 顺 序 通 过 ie 在 ie rp t t
基于DirectShow的p2p流媒体播放器的实现

[ 键 词 ] Die th w; 媒 体 播 放 器 ; 2 关 rcS o 流 pp [ 图 分 类 号 ]P3 7 中 , 1 I 【 献 标 识 码 ]A 文 [ 章 编 号 ]1 0 — 5 0( 0 7 0 一 1 8 0 文 09 9 3 2 0 )3 O 1— 3
基于 Di cS o r th软件 学院 , 徽 合 肥 2 0 5 ) 中 安 3 0 2
的实现
【 摘 要 】 文 章 介 绍 了一 种 基 于 Die th w 技 术 的 p p流 媒 体 播 放 器 , 要 着 重 于 几 项 关 键 技 术 : rcS o 2 主
Di cS o 是 微 软 公 司 提 供 的 一 套 在 据 并 将 其 导 入 过 滤 器 图 ; 换 过 滤 器 用 来 获 取 、 r th w e 转 处 Wid w n o s平 台 上 进 行 多 媒 体 处 理 的 开 发 包 . 多 媒 理 和 传 送 媒 体 数 据 . 它 包 括 分 离 视 频 和 音 频 的 切 为 体 流 的 捕 捉 和 回 放 提 供 了 强 有 力 的 支 持 运 用 分 过 滤 器 、 压 视 频 数 据 的 视 频 解 码 过 滤 器 、 压 解 解 Die th w . 们 可 以 很 方 便 地 播 放 从 本 地 文 件 和 音 频 数 据 的 音 频 解 码 过 滤 器 : 表 现 过 滤 器 用 来 在 rcS o 我 网 络 播 放 多 媒 体 流 . 支 持 W DM 驱 动 模 型 的 采 集 硬 件 上 表 现 媒 体 数 据 . 如 显 卡 和 声 卡 或 是 磁 盘 文 从
户 。 P P流 媒 体 的 应 用 是 在 P P文 件 交 换 的 基 础 2 2 上产 生 的 . 户 在互 联 网 上观 看 视 频 流媒 体 时 , 用 可
用directshow开发视频解码插件

7
用 drc h w开 发视 频 解码 插 件 i to es
李 晓静 刘 爱 玉 李 舜 昌 邵 兰英
( 南柴 油 机 股 份有 限公 司 , 南 2 0视 频 回 放 系 统 需 要 专 门 开 发 播 放 软 件 。 文 介 绍 了在 V sa c 十 中 利 用 Di c h w DK 定 传 本 i l + u rto S eS
键 函数 。
关 键 词 : 频 解 码 插 件 视
Di c h w rto eS
视 频 监 控 系统 在实 际 中具 有 广 泛 的应 用 范 围 , 核 心 其
技 术 包 括 视 频 数 据 的 采 集 、 缩 、 输 、 存 与 回 放 。本 文 压 传 保
样, 我们 可 以利用 一 个 .e 文件 方 便 地 描述 需 要 导 出 的函 df
随着 信 息技 术 的发 展 ,多媒 体 技 术 面 临 越来 越 多 的 挑 战 , 发 多媒 体 应用 程 序 愈发 复 杂 。 i c h w的设 计初 开 Dr t o eS
衷 就是 让 应 用 程 序 开 发人 员 从 复 杂 的数 据 传输 、硬 件 差
Dl eCa s betP I A E l t l O jc R V T G s
R ls e ae版 本 ,tn a.b mscti wn m.b e s b 1 、 vr 1 n s i .b、 im 1 i
V 目录之 前 , C 以便 编 译器 使 用最 新 版 本 的源 文件 。
2 2 Fl r 类 的 选 择 . ie 基 t 我 们 的 设 计 主 要 包 括 两 个 核 心 类 ,分 别 是 C ie t Fhr r C 和 C eo eS em, 其 中 , Fhr t控 制 文 件 数 据 的 管 理 , D cd dt a r C ieCr
关于DirectShow在Video视频处理方面的的一些基本应用

关于DirectShow在Video视频处理方面的的一些基本应用作者:佚名文章来源:不详点击数:8017更新时间:2005-10-6关于DirectShow在Video视频处理方面的的一些基本应用DirectShow是微软提供的DirectX软件开发包中的一员,主要以处理流媒体数据为重点开发的一套windows下的编程接口,为了高效地处理音视频数据,它向应用提供了直接访问系统底层功能的接口,可以使应用直接控制从数据采集到数据演播的各个中间环节,如数据压缩和解压缩格式等。
DirectShow是以一种比较新的概念来操作媒体流运行的,他有点类似于计算机硬件的管脚Pin的概念,并且引进了滤波器Filter和流图Graph等原理。
媒体流通过流图中的各个滤波器,最后到达输出界面,期间经过各个滤波器的转化和控制使最终数据达到一定的要求。
通过DirectShow的基本接口,应用可以自行设计自己的各种滤波器完成数据在流动中的特殊处理需求,比如视频数据流的格式从MPEG到RGB的变换(解压缩)或象素格式从YUV到RGB的变换等。
DirectShow本身是一个比较复杂的系统,其中包含了许多的概念,对于一个初涉的编程人员,需要学习许多新的知识,特别是对于使用非VC进行应用开发的人员,想要实际使用DirectShow的功能其困难程度是可想而知的。
为此,我这里提供一个折中的解决方案,使得非VC的开发人员也能方便的使用DirectSh ow提供的各种功能,同时也为所有希望进入视频编程领域的开发人员提供一个D irectShow的入门级引导。
这篇文章和相关源码或许能对感兴趣的读者提供一些帮助。
一、DirectShow的graph原理Graph实际上是一个filters的容器,Dshow提供一个Graph控件(Com),应用可以用CoCreateInstance来建立一个graph对象。
在Dshow中还有一个用于创建和操作Graph,这就是Builder对象,一般来讲,应用应该首先创建Build er对象,它是Dshow流控制的关键,Builder接口提供的方法包含了智能创建G raph中filters的能力,当未知媒体流格式时,使用Builder连接Filter时,将智能添加系统中的格式转换Filter到Graph的Filters链中产生目标格式的最佳转换链。
基于Directshow的VMR视频捕获的实现

时 , 捉 图像 帧 , 捕 然后 从 颜 色空 间 RG 转换 到 Y 4 0 12 , B UV 2 /4 0 供视 频 图像 处 理 算 法作 直接 处 理 。 如 : 码 、 别 等 。 比 编 识
关键词 : VMR ; rcso 视 频 捕 获 Di t w; e h
中 图分 类 号 : P 1 T 31
文 献标 识 码 : A
文 章编 号 :0 9 3 4 (0 0 2 — 1 0 0 1 0 — 0 42 1 )5 7 1 — 2
TheR e lz ton h de ai a i oft e Vi o Capt e Ba e lD ie tho ' ur s d Oi r cs w s VM R ZEN G ua h n. H —s a So N G u Y
I SSN 1 0 — 0 4 09 34
E ma l e u @C C .e . — i d f C Cn t a : c
h t : w w.n s e.a t / w dz. t p/ n c T l 8 — 5 - 6 0 6 5 9 94 e: 6 5 1 5 9 9 3 + 6O 6
Ke r s VM R ; i cs o v d o cp u e y wo d : dr t w; ie a t r e h
随 着 多媒 体 技 术 的 不断 发 展 , 于 视 频 技 术 的项 目已广 泛 应 用 于 数 字 监 控 、 视 电话 等 领 域 , 些 领 域 最 首 要 的 问题 是 实 时 图 基 可 这 像 捕 获 , 得 良好 的 视 频 图 像 以 供 数字 图像 处 理 , 典 的 D r t o ie n e 视频 捕 获 技 术 存 在 诸 多 局 限 性 , 对 这 一 现 象 , 获 经 i es w v or dr e h d e 针 本 文 提 出 了一 个 基 于 Dre hw 的 V i to es MR技 术 的 视频 捕 获 方 案 , 获 图 像 帧 , 换 颜 色空 间 , 视 频 图 像处 理算 法 处 理 。 捕 转 供
基于DirectShow的多媒体播放器设计与实现(含源文件)

编号毕业设计(论文)基于DirectShow的多媒体播放器设计与实现目录摘要 (I)Abstract (II)1 绪论 (1)1.1 课题研究的背景与意义 (1)1.2 课题国内外研究现状 (1)1.3 可行性分析 (2)1.3.1 技术可行性分析 (2)1.3.2 经济可行性分析 (2)1.3.3 管理可行性分析 (2)1.4 论文的主要内容及章节安排 (3)2 相关平台及开发技术简介 (3)2.1 Microsoft Visual C++ 2010概述 (3)2.1.1 MicosoftVisual C++ 2010特点 (3)2.1.2 MFC概述 (4)2.2 ADO访问数据库技术概述 (4)2.2.1 OLE DB和ADO简介 (4)2.2.2 ADO主要对象介绍 (5)2.2.3 VC++中使用ADO进行数据库开发的基本流程 (5)2.3 DirectShow核心技术 (5)2.3.1 DirectShow整体架构 (5)2.3.2 COM组件 (6)2.3.3 Filter概述及连接 (6)2.3.4 滤波器链表管理器 (7)2.3.5 滤波器链表中数据传输 (7)2.3.6 事件通知机制 (8)2.4 Skin++皮肤库概述 (9)2.4.1 Skin++简介 (9)2.4.2 Skin++特性 (9)3 系统需求分析 (9)3.1 系统业务需求 (9)3.2 系统数据需求 (10)3.3 功能需求 (10)3.4 非功能需求 (10)3.4.1 适应性 (10)3.4.2 安全性 (10)3.4.3 可靠性 (11)3.4.4 可扩充性 (11)3.4.5 可维护性 (11)3.4.6 可移植性 (11)4 多媒体播放器的设计 (11)4.1 系统功能设计 (11)4.1.1 媒体文件添加(数据输入) (11)4.1.2 媒体文件存储和显示(数据存储及显示) (12)4.1.3 媒体文件播放及控制(数据流传输、控制及输出) (12)4.2 系统结构设计 (12)4.3 系统数据库设计 (13)4.4 播放器滤波器链表结构设计 (13)4.5 DirectShow智能连接 (13)4.5.1 智能连接概述 (13)4.5.2 智能连接的实现 (14)5 多媒体播放器的实现 (14)5.1 基于DirectShow播放器的实现 (14)5.1.1 初始化COM (14)5.1.2 创建滤波器链表管理器 (15)5.1.3 智能连接建立滤波器链表 (15)5.2 DirectShow接口实现 (15)5.3 媒体文件信息存储实现 (15)5.3.1 数据库存储 (16)5.3.2 链表存储 (16)5.3.3 List列表显示 (17)5.4 播放控制功能的实现 (18)5.4.1 定位 (18)5.4.2 播放 (19)5.4.3 暂停、停止 (19)5.4.4 全屏 (19)5.4.5 截图 (20)5.4.6 静音控制 (20)5.4.7 速率控制 (21)5.4.8 上一个和下一个 (21)5.4.9 查找 (22)5.4.10 删除 (22)5.4.11 排行榜 (23)5.4.12 播放模式设置 (24)5.4.13 帮助 (24)5.4.14捕获本地摄像头 (25)5.5 歌词关联实现 (26)5.5.1 歌词构造原理概述 (26)5.5.2 获取歌词方法及过程 (27)5.5.3 遇到难点和问题 (27)5.6 用户管理功能实现 (28)5.6.1 用户注册 (28)5.6.2 用户登录 (29)5.6.3 用户使用系统整体流程 (29)5.7 播放JPG格式图片实现 (30)5.7.1 JPG格式图片缩放实现 (30)5.7.2 JPG格式图片的显示 (30)6 测试多媒体播放器实例及结论 (31)6.1 测试环境设计 (31)6.1.1 软件环境 (31)6.1.2 硬件环境 (32)6.2 测试用例设计 (32)6.3 测试结果分析 (33)6.3.1 多媒体播放器的主题界面 (33)6.3.2 多媒体播放器测试结果记录 (34)6.4 测试结论 (35)结束语 (35)致谢...................................................................................................... 错误!未定义书签。
基于DirectShow技术实现视频采集

Jn 08 u .2 0
文章 编 号 :0 8 6 2 2 0 ) 2 9 — 0 1 0 —8 5 ( 0 8 0 —0 7 4
基 于 Die t h w 技 术 实 现 视 频 采集 r cS o
郭 昊
( 安 电子 工 程 研 究 所 西 安 西 70 0 ) 1 1 0
【 要 】 介 绍 Di cS o 技 术 的 基 本 概 念 , 出 了基 于 D rcS o 技 术 采 集 视 频 数 据 的 软 摘 r thw e 提 i th w e 件 设 计 方 案 , 中 详 细 叙 述 了软 件 开 发 的 实 现 框 架 。 文 关键 词 : i cS o D r t h w;视 频 捕 获 ;过 滤 器 ;过 滤 器 图 表 e
现速 度 以及灵 活 性方 面具 有 很 大 的优 势 , 更重 要 的
种是 Di cS o r t h w。VF 是 Mi oot 1 9 e w c s f 于 9 2年 r
推 出 的 关 于 数 字 视 频 的 一 个 软 件 包 , W 给 视 频 VF
处理 带来 了较 大 的便 利 , 能 把 模 拟视 频 信 号转 换 它
为数 字信 号并 进 行播 放 。VF 的主 要 特 点 是视 频 w 采集 与设 备 无 关 。D rcS o 是 微 软 公 司推 出 的 i th w e
是 D rcS o 中很 多 标 准 库 的代 码 都 是 用 C十+ i th w e
或者 C语 言 实 现 的 , 视 频 采 集 系 统 采 用 D rc— 本 i t e S o 进 行开 发 , hw 以便 于灵 活 、 方便 地 操 作 硬 件并 获
放 , 对 Wid ws 台 , 软 提 供 了两 种 多 媒 体 开 针 no 平 微 发 框 架 : 种是 Vie o n o ( 一 d ofrWid ws 简称 VF w) 另 ,
DirectShow播放视频和MP3

二 、播 放 MP 3
DrcSo i thw和 Drc e i t e X中 的其 他组 件 - ,都是 基 于 c) 样 ( M
这些过滤器 由 Fl rrp 理它们 的连接 ,数 据在过 滤器 ieG ah管 t
现有的过滤器播放视频和 音频 。
、
播 放过 程
Drc hw 进 行 多媒 体处 理 是 由 一 过滤器 ( lr 完成 i to eS 些 ie ft )
的。这些过滤器分别完 成多媒体 流的部分处理过程 ,这些处理 过桴包括 :滨取文件 、网络媒体 流 ,或从视频 、音频设备捕获 媒体数据 ,这种过滤器 叫做源过滤器 (o reftr ;解码或编 Su l ) c ie 码 、流的分离与合成或格式转换 ,这种过 滤器 叫做 变换过滤器 (rnf m ft ) Tas r ie ;将数 据输 出到显示 适 配器 、声 卡或 文件或 o lr
#n ld <w id ws h> icu e no . #n ld <d h w . icu e s o h>
流媒体或者接 收过滤器事件。Fh r r h具有 智能 的特点 。连 ieGa p
接 两个 滤器 时 ,如果 它们 之 问的 的媒体 格 式不 相 同 ,Fl r ie t- G ah会 自动插 入合适 的解码器 rp .
‘
C S 1(NP OC U J rp B i e, L C __ R D G a h ul r )J d
- 一銎
维普资讯
…
…
…
…
…
…
…
…
…
…
…
…
…
基于DirectShow的AVI文件在局域网中的组播与接收

音频等多媒体文件的流媒体传输技术正被广泛关注。这种技
术允许用户不必等到整个文件下载完毕 ,而只需经过短暂的 启动延 时即可进行观看 。当多媒体数据在客户机上播放 时, 文件 的剩余部分将在后 台继续从流媒体服务器上下载 以供播
在 Flr r h ie Ga 运行的时候接收到各种事件, t p 并通过消息的方
h ss se C me t T i y t m a e VIfl s r q ie nt rv d o o e n . n A e ’ u r me i e n d ma d i e o f
[ e o d ]A I l F t ; i r r h F t a h n grMut a K y r s V e ie F t a ; i r r a e w i f ; l r l g p l g p ma e e ; l s i t c
2 Hih r d c t nR s ac igC ne , ’lJ oo gUn v ri , ’l7 0 4 ) . g e u ai e e r hn e trXi l i tn ie s y Xiat a d n c sfD r th w dv l m n p t r , m l i u i st h o g 。 ra i u i sss m f V l Abt c]B s r o i c o e p e t l f m e p yn I m lc te n l y a t m n m l atyt r I e r e o Mi o t e S e o a o o g P ta c o se g t e oA f s e i
随着多媒体技 术在网络上的广 泛应用,实 时传送视频、
媒体的演示,也可以输出到文件进行存储。
应用程序位于 Di cS o r th w系统之 上, 照一定的意图建 e 按 立起相应 的 Fl r rp ,然后通 过过滤器 图表管理器 ( ie ie ah t G Fl r t G ahMaa e)来控制整个数据 的处理过程 。Di cS o rp ng r r th w能 e
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的高清视频播放实现方法[发明专利]](https://img.taocdn.com/s3/m/5ef111726bec0975f565e29e.png)
专利名称:基于DirectShow的高清视频播放实现方法专利类型:发明专利
发明人:杨兵,白薇薇
申请号:CN201410416020.7
申请日:20140821
公开号:CN104159144A
公开日:
20141119
专利内容由知识产权出版社提供
摘要:本发明涉及一种基于DirectShow的高清视频播放方法,包括以下步骤:将高清视频数据通过编码形成H.264/AVC流格式的视频文件;利用DirectShow构建流媒体播放链路;通过源过滤器获取所述视频文件,并调用音视频分离器将所述视频文件分离出视频流和音频流;通过视频解码器将所述视频流解码形成非压缩格式的视频数据传输至视频渲染器,通过音频解码器将所述音频流解码出音频数据传输至音频渲染器;视频渲染器将非压缩格式的视频数据提交至显卡进行显示处理,音频渲染器将音频数据提交至声卡进行处理。
本发明可以实现4K等高清视频进行流畅的播放,解决了个人电脑等设备不能播放4K等高清视频的问题。
申请人:杨兵
地址:518000 广东省深圳市福田区福虹路4号华强公司宿舍
国籍:CN
代理机构:广州市南锋专利事务所有限公司
代理人:张志醒
更多信息请下载全文后查看。
基于DirectShow实现多路视频播放控制

基于DirectShow实现多路视频播放控制
许众威;钱小红
【期刊名称】《盐城工学院学报(自然科学版)》
【年(卷),期】2008(021)003
【摘要】针对低成本虚拟摄影棚系统中对虚拟场景生成子系统的要求,选择开发视频应用程序的好的设计模式-DirectShow技术,分析其体系结构的特点与组成,研究和实现了实时多路视频播放控制系统,并成功地把该系统应用于低成本虚拟摄影棚系统中.阐述了多路视频播放控制系统的分析、设计与实现.
【总页数】4页(P22-25)
【作者】许众威;钱小红
【作者单位】盐城工学院,电气与信息工程学院,江苏,盐城,224051;华为技术有限公司,广东,深圳,518129
【正文语种】中文
【中图分类】TP37
【相关文献】
1.利用VC++实现基于DirectShow的视频播放器开发 [J], 赵炯;陈力
2.基于DirectShow的流式立体视频播放器的设计与实现 [J], 方波;曾致远
3.基于DirectShow的MPEG-2流媒体多路播放与实时存储系统设计与实现 [J], 杜健;张白愚;杨莉云
4.基于 DirectShow的通用多路视频接口研究和实现 [J], 余胜生;苏曙光;周敬利
5.基于directshow的视频播放器设计与实现 [J], 伍开胜;罗宇;刘斌
因版权原因,仅展示原文概要,查看原文内容请购买。
VC++6.0平台下利用DirectShow技术实现DV设备的视频处理

VC++6.0平台下利用DirectShow技术实现DV设备的视频
处理
凌渝
【期刊名称】《警察技术》
【年(卷),期】2004(000)002
【摘要】本文主要介绍了在VC++6.0开发环境中,如何利用DirectShow技术实现对DV设备输出视频信号的预览、捕获和抓拍操作.
【总页数】4页(P14-17)
【作者】凌渝
【作者单位】公安部一所
【正文语种】中文
【中图分类】TP3
【相关文献】
1.基于DirectShow的视频处理Filter组件设计与实现 [J], 王新蕾;刘乃丰;夏济海
2.多路Netra视频处理平台SEED-DVS8168 [J], 艾睿合众公司
3.Windows 98下利用VC++6.0实现多线程技术的方法 [J], 应珊红
4.使用DirectShow技术实现DVD播放控制 [J], 鲁漫红
5.使用DirectShow技术实现DVD播放控制 [J], 鲁漫红
因版权原因,仅展示原文概要,查看原文内容请购买。
基于Directshow的视频缩放的技术措施

基于Directshow的视频缩放的技术措施本文从网络收集而来,上传到平台为了帮到更多的人,如果您需要使用本文档,请点击下载按钮下载本文档(有偿下载),另外祝您生活愉快,工作顺利,万事如意!在日常学习工作中经常会对各种视频文件进行分析,比如视频的剪切、缩放等,但是对于这些操作可能会用到专业的视频分析卡等硬件的支持。
针对硬件价值较高,微软提供了一套基于COM的流媒体处理开发包DirectShow。
在DirectShow中提供了完整的视频分析处理接口DES,负责对各类视频进行分析处理。
通过DES、Filter Graph可以对视频进行缩放处理,使视频的缩放脱离硬件的直接支持,适合于个人PC 机上的视频处理。
本文主要分析了3中视频缩放的方法,通过这些方法可以进一步加快视频缩放的速度和效率。
1 Directshow简介利用Directshow对视频进行缩放处理,必须对Directshow的架构,DES(Directshow Editing Services)以及Filter Graph Manager等知识有所了解。
Directshow的体系结构Directshow本质上就是基于COM组建的流媒体开发包,它为我们用户提供了一整套完整的视频处理接口。
该体系结构大致可分为3层:用户应用层、Directshow接口层、底部设备层。
Filter以及Filter Graph ManagerFilter其实就是一种叫做过滤器的COM组件,一共有三种类型的Filter:Source Filter、Transforill Filter、Rendering Filter。
它们都包含一个或多个Pin,Source Filter负责视频的采集,输入等;Transform Filter负责对视频进行格式转换、传输等;Rendering Filter负责视频文件的渲染,输出。
由于每一个Filter都有Pin针,我们可以根据不同的任务、需求,将各种Filter利用Pin针连接起来,就构成了一个Filter Graph。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
DirectShow 媒体文件回放总结收藏作者:Inkick1.概述DirectShow中媒体文件回放的过程也就是一个为媒体文件选择相应所需的Filter、构建Filter Graph、并对Filter Graph的状态进行维持、控制的过程。
这里所说的媒体文件,不仅仅是指音频、视频文件,同时也包括bmp、jpeg、gif等图形图像格式以及midi等数字化音乐序列。
因此,使用DirectShow进行媒体文件的回放需要经过以下的步骤:2.构建Filter GraphFilter Graph为Filter提供了一个容器,一个构建完整的Filter Graph也就是一个完整的Filter 连路,这个连路对于程序是透明的,可控制的。
而对于每一个媒体文件来说,Filter Graph 与媒体文件存在着对应的关系。
也就是说,一个Filter Graph只能实现一个(种)文件的回放。
在DirectShow中,Filter Graph是由接口对象IGraphBuilder实现的,我们可以调用Win32 API 函数CoCreateInstance()建立一个实体。
Filter Graph实体建立之后并不具有任何的Filter,因此不具有任何实际用途。
因此我们需要连接需要的Filter来完成FilterGraph的构建。
智能连接这个术语覆盖了一系列Filter Graph Manager用于构建所有或部份filter graph的算法。
任何时候,当Filter Graph Manager需要添加filter来完成graph时,它大致做以下几件事情:如果有一个filter存在于graph中,而且这个filter有至少一个没有连接的input pin,Filter Graph Manager试着去试用这个filter。
否则,Filter Graph Manager在已注册的filter中寻找连接时可以接受合适的媒体类型的filter。
每一个filter都注册有一个Merit值,这个值用以标记哪个filter最容易被Filter Graph Manager 选中来完成graph。
Filter Graph Manager按Merit值的顺序来选择filter,Merit值越大,被选中的机会越大。
对于每种流类型(如音频、视频、MIDI),默认的renderer具有一个很高的Merit值,解码器同样是,专用filter具有低Merit值。
如果Filter Graph Manager选择的filter不合适,它会返回来尝试另外的filter组合。
我们有三种构建graph的途径:1.filter graph manager构建整个graph2.filter graph manager构建部分graph3.应用程序构建整个graph2.1 RenderFileIGraphBuilder提供了多种智能完成FilterGraph构建的方法。
最简单的是使用接口方法IGraphBuilder::RenderFile。
HRESULT RenderFile(LPCWSTR lpwstrFile, LPCWSTR lpwstrPlayList);第一个参数为文件的路径(祥见后文),第二个参数保留,必须为空。
这个方法需要一个表示媒体文件路径或者URL的Unicode字符串参数。
而我们通过界面获得的文件路径的字符串往往是ANSI字符串。
我们可以使用下面方法进行转换:包含头文件:#include <tchar.h>#include <atlbase.h>这两个头文件包含了ANSI字符串与Unicode字符串相互转化的函数与宏使用宏:USES_CONVERSION;定义一个WCHAR的数组:WCHAR FileName[MAX_PA TH];而MAX_PA TH是在windef.h中定义的:#define MAX_PA TH 260这与windows路径最大字符为260个相符。
这个数组保存转化后的Unicode形式表示的路径。
然后可以使用下面的函数进行转换:(假定以ANSI形式给出的字符串为szFile)wcsncpy (FileName, T2W(szFile), NUMELMS(wFile)-1);FileName[MAX_PA TH-1] = 0;wcsncpy的原型:wchar_t *wcsncpy( wchar_t *strDest, const wchar_t *strSource, size_t count );这个函数的作用类似于strcpy,是实现字符串之间的复制。
只不过,这是一个用在Unicode 上的版本。
第一个参数指定了字符串转化后的存放地址,也就是我们要得到的Unicode字符串,第二个参数指定了要转化的字符串的来源地址,也就是我们要转化的ANSI字符串。
在第二个参数使用了宏T2W(szFile),这个宏可以把一个ANSI字符串转为一个WCHAR类型的字符串。
第三个参数为转化字符串中字符的数量。
现在问题出来了,这个函数的第二个参数需要宽字符串的地址,如果我们有这样的一个地址,我们还转换什么?因此这个的关键在于T2W上面。
让我们来看一下T2W的定义。
这个定义在头文件A TLCONV.H里面(只保留我们比较感兴趣的部分)。
#ifdef _UNICODEinline LPWSTR T2W(LPTSTR lp) { return lp; }inline LPTSTR W2T(LPWSTR lp) { return lp; }#else#define T2W A2W#endif我们可以看到,如果定义了_UNICODE,则T2W直接返回将要转化的字符串,这是因为在Unicode环境下,ANSI字符拥有和Unicode字符同样的宽度。
也就是说,ANSI是Unicode 的一个子集。
但是在非Unicode环境下,就将T2W替换成A2W,这样我们返回来看A2W 的定义(这个定义在同样的头文件中):#define A2W(lpa) (\((LPCSTR)lpa == NULL) ? NULL : (\_convert = (lstrlenA(lpa)+1),\A TLA2WHELPER((LPWSTR) alloca(_convert*2), lpa, _convert)))宏定义比较晦涩,我们转换成比较好理解的函数形式:LPCSTR A2W(LPTSTR lpa){if(lpa == NULL){return NULL;}_convert = (lstrlen(A)(lpa)+1);AtlA2WHelper ((LPWSTR)alloca(_covert*2),lpa,_convert);return lpa;}这个函数的结构比较清晰,首先判断是不是空字符串,如果是空字符串就返回空,因为ANSI 和Unicode意义上的空字符串都是NULL,如果不为空,则开始转换。
重点是函数A TLA2WWHELPER(),这个函数的实现部分在A TLCONV.CPP中:LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars){_ASSERTE(lpa != NULL);_ASSERTE(lpw != NULL);lpw[0] = '\0';MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars);return lpw;}这个函数除了做一些必要的安全性判定以及前序准备以外,核心工作是调用了一个函数MultiByteToWideChar,因此我们还要继续深入。
这次我们发现我们找不到源代码了,但是在MSDN中我们可以得到明确的提示:int MultiByteToWideChar(UINT CodePage, // code pageDWORD dwFlags, // character-type optionsLPCSTR lpMultiByteStr, // address of string to mapint cchMultiByte, // number of bytes in stringLPWSTR lpWideCharStr, // address of wide-character bufferint cchWideChar // size of buffer);这个API函数接受六个参数(Win32 API的风格——参数超多),第一个参数指定了CodePage(解释见附录5.1),在这里我们可以指定CP_ACP,来表示我们选择ANSI Code Page 代表我们要转换的源字符串编码形式为ANSI,第二个参数是一组位标志,决定了如何处理原字符串中的控制字符或者无效字符。
一般指定MB_PRECOMPOSED,第三个参数是源字符串的地址(或者指针)。
第四个字参数是要转化的字符串里面包含了多少个字符,第五个参数指定了转换后的字符串的存放地址,第六个参数指定了转换后字符串的Buffer的大小,也就是转换后占用内存空间的多少。
现在我们逐层返回,(如果你已经忘记了我们的初衷是什么建议你听一下F.I.R的歌),根据最核心的函数MultiByteToWideChar的分析,我们可以得出AtlA2Whelper几个参数的含义:AtlA2WHelper( LPWSTR lpw, //转化的目标字符串的地址LPCSTR lpa, //转化的源字符串的地址int nChars //源字符串中包含的字符数)因此在判断lpw以及lpa不为空之后便直接调用:lpw[0] = '\0';MultiByteToWideChar(CP_ACP, 0, lpa, -1, lpw, nChars);我们已经返回到了那个宏,还是让我们来看我们改写的那个函数吧:_convert = (lstrlen(A)(lpa)+1);AtlA2WHelper ((LPWSTR)alloca(_covert*2),lpa,_convert);return lpa;lstrlen函数得到参数字符串的长度(对于ANSI字符串来说是字节数,对于Unicode字符串来说是字符数),后面的(A)表明参数字符串为ANSI字符串,经过这个参数的调用,_convert 的值变成了要转换的字符串长度加一。
为什么要加一呢?因为字符串的结尾要补上一个’\0’,我们总要为这个’\0’预留空间。
下一步就是要申请空间来保存转化完成的字符串了,使用(LPWSTR)alloca(_covert*2),分配字符串数的两倍空间(因为Unicode字符占用的空间是ANSI的两倍),然后将地址转为LPWSTR,当作参数传递给AtlA2Whelper,开始转换,任务完成!可是,真的完成了吗?那个该死的_convert是哪里来的?哈哈,还记得我们一开始说的吗?回忆一下,在使用T2W之前要做的工作是什么?使用宏USES_CONVERSION;!为什么呢?我们继续看这个宏的定义:#ifndef _DEBUG#else#define USES_CONVERSION int _convert = 0#endif看到了吗?这个宏其实就是在定义这个_convert变量。