wince下用DirectShow播放音频和视频

//========================================================================
//TITLE:
// wince下用DirectShow播放音频和视频
//AUTHOR:
// norains
//DATE:
// Monday 14-May-2007
//Environment:
// WinCE 5.0
//========================================================================

虽然网上关于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:消息的参数.


那么,现在以接收一个视频播放结束事件的代码片段为例子:
//自定义一个消息
#defineWM_GRAPHNOTIFY(WM_USER+13)

//设置接收消息窗口和消息
m_pMedia->SetVideoWindow(hWnd,WM_GRAPHNOTIFY,NULL);

...

//这个是消息循环函数
LRESULTCMainWnd::WndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
...{
switch(wMsg)
...{

...

caseWM_GRAPHNOTIFY:
...{
LONGevCode,evParam1,evParam2;

//获取此时的DirectShow事件
if(m_pMedia->GetEvent(&evCode,&evParam1,&evParam2)==TRUE)
...{
if(evCode==EC_COMPLETE)
...{
MessageBox(NULL,TEXT(
"播放完毕"),TEXT(""),MB_OK);
}

}

return0;
}

}


...

}


好了,知道播放完毕,就这么简单.恩,还很复杂..?呵呵,我觉得已经很简单了.

文章的最后,让我们再来看看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:interfacefortheCMediaclass.
//
//Version:
//1.2.0
//Date:
//2007.05.08
/**///////////////////////////////////////////////////////////////////////
#ifndefMEDIA_H
#defineMEDIA_H


#include
<mmsystem.h>
#include
<streams.h>

//--------------------------------------------------------------------
//Macrodefine

//Thevolumevalue
#defineMAX_VOLUME0
#defineMIN_VOLUME-10000

//Thebalancevalue
#defineMAX_BALANCE10000
#defineMIN_BALANCE-10000

//--------------------------------------------------------------------
//Enumvalue

enumDISPLAYMODE
...{
//Fittotheplaywindowsize.Howwide(height)thewindowis,how
//isthemove.Keepaspectratio.
DISP_FIT,

//Stretchtotheplaywindowsize.Don'tkeeptheaspectratio.
DISP_STRETCH,

//Fullscreenplay.
DISP_FULLSCREEN,

//Whenthesizeofvideoissmallerthantheplaywindow,itdisplayes
//asthevideosize.Ifit'sbigger,itjustliketheDISP_FITmode.
DISP_NATIVE
}
;
//--------------------------------------------------------------------

//Themediafileproperty
typedefstruct
...{
//Thevolumerangeis–10,000to0.
//Divideby100togetequivalentdecibelvalue(forexample–10,000=–100dB).
LONGlVolume;

//Thevaluefrom–10,000to10,000indicatingthestereobalance
//AswiththeVolumeproperty,unitscorrespondto.01decibels(multipliedby–1whenplBalanceisapositivevalue).
//Forexample,avalueof1000indicates–10dBontherightchanneland–90dBontheleftchannel.
LONGlBalance;

//Widthofthevideo
LONGlWidth;

//Heightofthevideo
LONGlHeight;

//Approximatebitrate
LONGlBitRate;

}
MEDIAPROPERTY,*PMEDIAPROPERTY;
//--------------------------------------------------------------------
classCMedia
...{
public:
BOOLGetEvent(LONG
*plEvCode,LONG*plParam1,LONG*plParam2);
BOOLSetNotifyWindow(HWNDhWnd,UINTwMsg,
longlInstanceData);
BOOLSetVolume(LONGlVolume,LONGlBalance
=0);
BOOLSetDisplayMode(DISPLAYMODEmode);
BOOLGetMediaProperty(PMEDIAPROPERTYpOutProperty);
staticCMedia*GetInstance();
voidClose();
BOOLCheckVisibility();
voidSetVideoWindow(HWNDhWndVideo);
BOOLOpen(TCHAR
*pszFileName);
BOOLStop();
BOOLPause();
BOOLPlay();
virtual~CMedia();

protected:


CMedia();

//Collectionofinterfaces
IGraphBuilder*m_pGB;
IMediaControl
*m_pMC;
IMediaEventEx
*m_pME;
IVideoWindow
*m_pVW;
IBasicAudio
*m_pBA;
IBasicVideo
*m_pBV;
IMediaSeeking
*m_pMS;

TCHARm_szFileName[MAX_PATH];
HWNDm_hWndVideo;
//Thewindowplayvideo
HWNDm_hWndNotify;//Thewindownotify
BOOLm_bExitThrd;
BOOLm_bThrdRunning;
staticCMedia*m_pInstance;
DISPLAYMODEm_DispMode;

}
;

#endif//#ifndefMEDIA_H





/**///////////////////////////////////////////////////////////////////////
//Media.cpp:implementationoftheCMediaclass.
//
/**///////////////////////////////////////////////////////////////////////

#include
"stdafx.h"
#include
"Media.h"


//----------------------------------------------------------------------------------------------
//Macrodefine

//Defaultplaymode
#defineDEFAULT_DISPLAY_MODEDISP_NATIVE

//----------------------------------------------------------------------
//Initialize
CMedia*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)
...{
deletem_pInstance;
m_pInstance
=NULL;
}


}





//------------------------------------------------------------
//Description:
//Playthemediafile
//Whenyoucallthefunction,youshouldcallOpen()before.
//
//-------------------------------------------------------------
BOOLCMedia::Play()
...{
//Runthegraphtoplaythemediafile

if(m_pMC==NULL)
...{
returnFALSE;
}





m_pMC
->Run();

returnTRUE;
}





//------------------------------------------------------------
//Description:
//Pause.
//Whenyoucallthefunction,youshouldcallOpen()before.
//
//-------------------------------------------------------------
BOOLCMedia::Pause()
...{

if(m_pMC==NULL)
...{
returnFALSE;
}


m_pMC
->Pause();

returnTRUE;
}





//------------------------------------------------------------
//Description:
//Stop.
//Whenyoucallthefunction,youshouldcallOpen()before.
//
//-------------------------------------------------------------
BOOLCMedia::Stop()
...{

if(m_pMC==NULL||m_pMS==NULL)
...{
returnFALSE;
}



m_pMC
->Stop();
m_pMS
->SetPositions(0,AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning);

returnTRUE;
}





//--------------------------------------------------------------------------
//Description:
//Openthemediafile.Whensucceedincallingthefunction,
//youshouldcalltheClose()toreleasetheresource
//
//-------------------------------------------------------------------------
BOOLCMedia::Open(TCHAR*pszFileName)
...{
BOOLbResult
=FALSE;


if(_tcslen(pszFileName)>=MAX_PATH)
...{
gotoEND;
}

else
...{
_tcscpy(m_szFileName,pszFileName);

//Checkthefileexisting
HANDLEhdFile=CreateFile(m_szFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);
if(hdFile==INVALID_HANDLE_VALUE)
...{
//Thefiledoesn'texist
gotoEND;
}

else
...{
CloseHandle(hdFile);
}

}






//InitializeCOM
if(CoInitializeEx(NULL,COINIT_MULTITHREADED)!=S_OK)
...{
gotoEND;
}


//GettheinterfaceforDirectShow'sGraphBuilder
if(CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&m_pGB)!=S_OK)
...{
gotoEND;
}



//Havethegraphconstructitstheappropriategraphautomatically
if(m_pGB->RenderFile(m_szFileName,NULL)!=NOERROR)
...{
gotoEND;
}



//QueryInterfaceforDirectShowinterfaces
if(m_pGB->QueryInterface(IID_IMediaControl,(void**)&m_pMC)!=NOERROR)
...{
gotoEND;
}

if(m_pGB->QueryInterface(IID_IMediaEventEx,(void**)&m_pME)!=NOERROR)
...{
gotoEND;
}

if(m_pGB->QueryInterface(IID_IMediaSeeking,(void**)&m_pMS)!=NOERROR)
...{
gotoEND;
}



//Queryforvideointerfaces,whichmaynotberelevantforaudiofiles
if(m_pGB->QueryInterface(IID_IVideoWindow,(void**)&m_pVW)!=NOERROR)
...{
gotoEND;
}

if(m_pGB->QueryInterface(IID_IBasicVideo,(void**)&m_pBV)!=NOERROR)
...{
gotoEND;
}



//Queryforaudiointerfaces,whichmaynotberelevantforvideo-onlyfiles
if(m_pGB->QueryInterface(IID_IBasicAudio,(void**)&m_pBA)!=NOERROR)
...{
gotoEND;
}


//Isthisanaudio-onlyfile(novideocomponent)?
if(CheckVisibility()==TRUE)
...{
if(m_pVW->put_Owner((OAHWND)m_hWndVideo)!=NOERROR)
...{
gotoEND;
}



if(m_pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN)!=NOERROR)
...{
gotoEND;
}

}




//Setplaymode
SetDisplayMode(m_DispMode);


bResult
=TRUE;

END:

if(bResult==FALSE)
...{
//Releasetheresource
Close();
}


returnbResult;
}





//------------------------------------------------------------
//Description:
//Thismethodsetsanowningparentforthevideowindow.
//
//Parameters:
//hWnd:[in]Handleofnewownerwindow.
//
//----------------------------------------------------------
voidCMedia::SetVideoWindow(HWNDhWndVideo)
...{
m_hWndVideo
=hWndVideo;
}




//------------------------------------------------------------
//Description:
//Checkthefilevisibility
//Whenyoucallthefunction,youshouldcallOpen()before.
//
//Parameters:
//TRUE:Video
//FALSE:It'snotthevideo
//
//------------------------------------------------------------
BOOLCMedia::CheckVisibility()
...{


if(!m_pVW)
...{
//NoVideoWindowinterface.Assumingaudio/MIDIfileorunsupportedvideocodec
returnFALSE;
}


if(!m_pBV)
...{
//NoBasicVideointerface.Assumingaudio/MIDIfileorunsupportedvideocodec.
returnFALSE;
}



//Ifthisisanaudio-onlyclip,get_Visible()won'twork.
//
//Also,ifthisvideoisencodedwithanunsupportedcodec,
//wewon'tseeanyvideo,althoughtheaudiowillworkifitis
//ofasupportedformat.
longlVisible;
if(m_pVW->get_Visible(&lVisible)!=NOERROR)
...{
returnFALSE;
}



returnTRUE;
}





//------------------------------------------------------------
//Description:
//ReleasetheresourcewhichopenedintheOpen()
//
//------------------------------------------------------------
voidCMedia::Close()
...{

//Relinquishownership(IMPORTANT!)afterhiding
if(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;
}


//FinishedwithCOM
memset(m_szFileName,0,sizeof(m_szFileName));


CoUninitialize();
}



//------------------------------------------------------------
//Description:
//Gettheinstanceofobject
//
//------------------------------------------------------------
CMedia*CMedia::GetInstance()
...{
if(m_pInstance==NULL)
...{
m_pInstance
=newCMedia();
}


returnm_pInstance;
}





//------------------------------------------------------------
//Description:
//Getthemediafileproperty.
//Whenyoucallthefunction,youshouldcallOpen()before.
//
//------------------------------------------------------------
BOOLCMedia::GetMediaProperty(PMEDIAPROPERTYpOutProperty)
...{

MEDIAPROPERTYprop
=...{0};

if(m_pBA==NULL||m_pBV==NULL)
...{
returnFALSE;
}



//Gettheaudioproperty
m_pBA->get_Volume(&prop.lVolume);
m_pBA
->get_Balance(&prop.lBalance);


//Getthevideoproperty
if(CheckVisibility()==TRUE)
...{
m_pBV
->get_BitRate(&prop.lBitRate);
m_pBV
->GetVideoSize(&prop.lWidth,&prop.lHeight);

}


*pOutProperty=prop;


returnTRUE;
}



//------------------------------------------------------------
//Description:
//Setthedisplaymode.
//Whenyoucallthefunction,youshouldcallOpen()before.
//
//------------------------------------------------------------
BOOLCMedia::SetDisplayMode(DISPLAYMODEmode)
...{
if(m_pVW==NULL)
...{
returnFALSE;
}


m_DispMode
=mode;

if(mode==DISP_FULLSCREEN)
...{
m_pVW
->put_FullScreenMode(OATRUE);
}

else
...{
//Restoretothenormalmode
m_pVW->put_FullScreenMode(OAFALSE);

RECTrcWnd
=...{0};
GetClientRect(m_hWndVideo,
&rcWnd);
LONGlWndWidth
=rcWnd.right-rcWnd.left;
LONGlWndHeight
=rcWnd.bottom-rcWnd.top;

MEDIAPROPERTYprop
=...{0};
GetMediaProperty(
&prop);


if(mode==DISP_FIT||mode==DISP_NATIVE)
...{
LONGlDispLeft,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;
}

elseif(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);
}

elseif(mode==DISP_STRETCH)
...{

m_pVW
->put_Left(0);
m_pVW
->put_Top(0);
m_pVW
->put_Width(lWndWidth);
m_pVW
->put_Height(lWndHeight);
}


}




returnTRUE;
}



//------------------------------------------------------------
//Description:
//Setthevolume.
//Whenyoucallthefunction,youshouldcallOpen()before.
//
//Parameters:
//lVolume:[in]Thevolume(amplitude)oftheaudiosignal.
//Rangeis–10,000to0.
//lBalance:[in]Thebalancefortheaudiosignal.Defaultvalueis0.
//Thevaluefrom–10,000to10,000indicatingthestereobalance.
//
//------------------------------------------------------------
BOOLCMedia::SetVolume(LONGlVolume,LONGlBalance)
...{
if(m_pBA==NULL)
...{
returnFALSE;
}


if(lVolume<MIN_VOLUME&&lVolume>MAX_VOLUME&&lBalance<MIN_BALANCE&&lBalance>MAX_BALANCE)
...{
returnFALSE;
}


m_pBA
->put_Volume(lVolume);
m_pBA
->put_Balance(lBalance);

returnTRUE;
}





//----------------------------------------------------------------------
//Description:
//Registersawindowthatwillhandlemessageswhenaspecifiedeventoccurs.
//
//Parameters:
//hWnd:[in]Handleofwindowtonotify.PassNULLtostopnotification.
//wMsg:[in]Windowmessagetobepassedasthenotification.
//lInstanceData:[in]Value(instancedata)tobepassedasthelParamparameterforthelMsgmessage.
//
//-----------------------------------------------------------------------------
BOOLCMedia::SetNotifyWindow(HWNDhWnd,UINTwMsg,longlInstanceData)
...{
if(m_pME==NULL)
...{
returnFALSE;
}


m_pME
->SetNotifyWindow((OAHWND)hWnd,wMsg,lInstanceData);

returnTRUE;
}



//----------------------------------------------------------------------
//Description:
//Thismethodretrievesthenotificationevent.
//
//-----------------------------------------------------------------------
BOOLCMedia::GetEvent(LONG*plEvCode,LONG*plParam1,LONG*plParam2)
...{
if(m_pME==NULL)
...{
returnFALSE;
}


LONGevCode,evParam1,evParam2;

if(m_pME->GetEvent(&evCode,&evParam1,&evParam2,0)==NOERROR)
...{
*plEvCode=evCode;
*plParam1=evParam1;
*plParam2=evParam2;

//Spinthroughtheevents
m_pME->FreeEventParams(evCode,evParam1,evParam2);
}

else
...{
returnFALSE;
}



returnTRUE;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值