/**************************************************************************************************************
如何使用COM接口,这里提供一个代码很短, 功能不简单, 阅读起来非常清晰的例子。
通过这个例子,读者不但可以学会用DirectShow编程播放视频文件,还能对COM接口的
原理有所了解。这个例子在YC++下编译执行。若要在其它环境中编译,则需增加一些声明。
读者有什么问题可在下面的评论中提出,本人将与您讨论。
**************************************************************************************************************/
void main()
{
void play_mpeg(wchar_t *m_name);
play_mpeg(L"d://mpeg//mpg.mpg"); //播放视频文件: d://mpeg//mpg.mpg
}
const GUID IID_IUnknown = {0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
struct IUnknown
{
virtual int stdcall QueryInterface(const GUID *riid, void **ppvObject) = 0;
virtual unsigned int stdcall AddRef() = 0;
virtual unsigned int stdcall Release() = 0;
};
//auto("...") {...} 是YC++扩展语法。表示本程序要使用动态库ole32.dll中的三个函数,
//这个语法可代替库文件 ole32.lib
auto("ole32.dll")
{
int stdcall CoInitialize(void *pvReserved);
void stdcall CoUninitialize();
int stdcall CoCreateInstance(const GUID *rclsid,IUnknown *pUnkOuter,unsigned int dwClsContext,const GUID *riid,void **ppv);
}
const GUID CLSID_FilterGraph = {0xe436ebb3,0x524f,0x11ce,{0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID IID_IMediaControl = {0x56a868b1,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID IID_IVideoWindow = {0x56a868b4,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID IID_IBasicVideo = {0x56a868b5,0x0ad4,0x11ce,{0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70}};
const GUID IID_IMediaSeeking = {0x36b73880,0xc2c8,0x11cf,{0x8b,0x46,0x00,0x80,0x5f,0x6c,0xef,0x60}};
const GUID TIME_FORMAT_FRAME = {0x7b785570, 0x8c82, 0x11cf,{0xbc, 0xc, 0x0, 0xaa, 0x0, 0xac, 0x74, 0xf6}};
struct IDispatch : public IUnknown
{
virtual int stdcall GetTypeInfoCount(int *pctinfo) = 0;
virtual int stdcall GetTypeInfo(int iTInfo,int lcid,void **ppTInfo) = 0;
virtual int stdcall GetIDsOfNames(GUID *riid,wchar_t **rgszNames,int cNames,int lcid,int *rgDispId) = 0;
virtual int stdcall Invoke(int dispIdMember,GUID *riid,int lcid,short wFlags,void *pDispParams,void *pVarResult,void *pExcepInfo,int *puArgErr) = 0;
};
struct IMediaSeeking : public IUnknown
{
virtual int stdcall GetCapabilities(unsigned int *pCapabilities) = 0;
virtual int stdcall CheckCapabilities(unsigned int *pCapabilities) = 0;
virtual int stdcall IsFormatSupported(GUID *pFormat) = 0;
virtual int stdcall QueryPreferredFormat(GUID *pFormat) = 0;
virtual int stdcall GetTimeFormatA(GUID *pFormat) = 0;
virtual int stdcall IsUsingTimeFormat(GUID *pFormat) = 0;
virtual int stdcall SetTimeFormat(const GUID *pFormat) = 0;
virtual int stdcall GetDuration(int64 *pDuration) = 0;
virtual int stdcall GetStopPosition(int64 *pStop) = 0;
virtual int stdcall GetCurrentPosition(int64 *pCurrent) = 0;
virtual int stdcall ConvertTimeFormat(int64 *pTarget,GUID *pTargetFormat,int64 Source,GUID *pSourceFormat) = 0;
virtual int stdcall SetPositions(int64 *pCurrent,unsigned int dwCurrentFlags,int64 *pStop,unsigned int dwStopFlags) = 0;
virtual int stdcall GetPositions(int64 *pCurrent,int64 *pStop) = 0;
virtual int stdcall GetAvailable(int64 *pEarliest,int64 *pLatest) = 0;
virtual int stdcall SetRate(double dRate) = 0;
virtual int stdcall GetRate(double *pdRate) = 0;
virtual int stdcall GetPreroll(int64 *pllPreroll) = 0;
};
struct IMediaControl : public IDispatch
{
virtual int stdcall Run() = 0;
virtual int stdcall Pause() = 0;
virtual int stdcall Stop() = 0;
virtual int stdcall GetState(int msTimeout,int *pfs) = 0;
virtual int stdcall RenderFile(wchar_t *strFilename) = 0;
virtual int stdcall AddSourceFilter(wchar_t *strFilename,struct IDispatch **ppUnk) = 0;
virtual int stdcall get_FilterCollection(struct IDispatch **ppUnk) = 0;
virtual int stdcall get_RegFilterCollection(struct IDispatch **ppUnk) = 0;
virtual int stdcall StopWhenReady() = 0;
};
struct IVideoWindow : public IDispatch
{
virtual int stdcall put_Caption(wchar_t *strCaption) = 0;
virtual int stdcall get_Caption(wchar_t **strCaption) = 0;
virtual int stdcall put_WindowStyle(int WindowStyle) = 0;
virtual int stdcall get_WindowStyle(int *WindowStyle) = 0;
virtual int stdcall put_WindowStyleEx(int WindowStyleEx) = 0;
virtual int stdcall get_WindowStyleEx(int *WindowStyleEx) = 0;
virtual int stdcall put_AutoShow(int AutoShow) = 0;
virtual int stdcall get_AutoShow(int *AutoShow) = 0;
virtual int stdcall put_WindowState(int WindowState) = 0;
virtual int stdcall get_WindowState(int *WindowState) = 0;
virtual int stdcall put_BackgroundPalette(int BackgroundPalette) = 0;
virtual int stdcall get_BackgroundPalette(int *pBackgroundPalette) = 0;
virtual int stdcall put_Visible(int Visible) = 0;
virtual int stdcall get_Visible(int *pVisible) = 0;
virtual int stdcall put_Left(int Left) = 0;
virtual int stdcall get_Left(int *pLeft) = 0;
virtual int stdcall put_Width(int Width) = 0;
virtual int stdcall get_Width(int *pWidth) = 0;
virtual int stdcall put_Top(int Top) = 0;
virtual int stdcall get_Top(int *pTop) = 0;
virtual int stdcall put_Height(int Height) = 0;
virtual int stdcall get_Height(int *pHeight) = 0;
virtual int stdcall put_Owner(int Owner) = 0;
virtual int stdcall get_Owner(int *Owner) = 0;
virtual int stdcall put_MessageDrain(int Drain) = 0;
virtual int stdcall get_MessageDrain(int *Drain) = 0;
virtual int stdcall get_BorderColor(int *Color) = 0;
virtual int stdcall put_BorderColor(int Color) = 0;
virtual int stdcall get_FullScreenMode(int *FullScreenMode) = 0;
virtual int stdcall put_FullScreenMode(int FullScreenMode) = 0;
virtual int stdcall SetWindowForeground(int Focus) = 0;
virtual int stdcall NotifyOwnerMessage(int hwnd,int uMsg,int wParam,int lParam) = 0;
virtual int stdcall SetWindowPosition(int Left,int Top,int Width,int Height) = 0;
virtual int stdcall GetWindowPosition(int *pLeft,int *pTop,int *pWidth,int *pHeight) = 0;
virtual int stdcall GetMinIdealImageSize(int *pWidth,int *pHeight) = 0;
virtual int stdcall GetMaxIdealImageSize(int *pWidth,int *pHeight) = 0;
virtual int stdcall GetRestorePosition(int *pLeft,int *pTop,int *pWidth,int *pHeight) = 0;
virtual int stdcall HideCursor(int HideCursor) = 0;
virtual int stdcall IsCursorHidden(int *CursorHidden) = 0;
};
struct IBasicVideo : public IDispatch
{
virtual int stdcall get_AvgTimePerFrame(double *pAvgTimePerFrame) = 0;
virtual int stdcall get_BitRate(int *pBitRate) = 0;
virtual int stdcall get_BitErrorRate(int *pBitErrorRate) = 0;
virtual int stdcall get_VideoWidth(int *pVideoWidth) = 0;
virtual int stdcall get_VideoHeight(int *pVideoHeight) = 0;
virtual int stdcall put_SourceLeft(int SourceLeft) = 0;
virtual int stdcall get_SourceLeft(int *pSourceLeft) = 0;
virtual int stdcall put_SourceWidth(int SourceWidth) = 0;
virtual int stdcall get_SourceWidth(int *pSourceWidth) = 0;
virtual int stdcall put_SourceTop(int SourceTop) = 0;
virtual int stdcall get_SourceTop(int *pSourceTop) = 0;
virtual int stdcall put_SourceHeight(int SourceHeight) = 0;
virtual int stdcall get_SourceHeight(int *pSourceHeight) = 0;
virtual int stdcall put_DestinationLeft(int DestinationLeft) = 0;
virtual int stdcall get_DestinationLeft(int *pDestinationLeft) = 0;
virtual int stdcall put_DestinationWidth(int DestinationWidth) = 0;
virtual int stdcall get_DestinationWidth(int *pDestinationWidth) = 0;
virtual int stdcall put_DestinationTop(int DestinationTop) = 0;
virtual int stdcall get_DestinationTop(int *pDestinationTop) = 0;
virtual int stdcall put_DestinationHeight(int DestinationHeight) = 0;
virtual int stdcall get_DestinationHeight(int *pDestinationHeight) = 0;
virtual int stdcall SetSourcePosition(int Left,int Top,int Width,int Height) = 0;
virtual int stdcall GetSourcePosition(int *pLeft,int *pTop,int *pWidth,int *pHeight) = 0;
virtual int stdcall SetDefaultSourcePosition() = 0;
virtual int stdcall SetDestinationPosition(int Left,int Top,int Width,int Height) = 0;
virtual int stdcall GetDestinationPosition(int *pLeft,int *pTop,int *pWidth,int *pHeight) = 0;
virtual int stdcall SetDefaultDestinationPosition() = 0;
virtual int stdcall GetVideoSize(int *pWidth,int *pHeight) = 0;
virtual int stdcall GetVideoPaletteEntries(int StartIndex,int Entries,int *pRetrieved,int *pPalette) = 0;
virtual int stdcall GetCurrentImage(int *pBufferSize,int *pDIBImage) = 0;
virtual int stdcall IsUsingDefaultSource() = 0;
virtual int stdcall IsUsingDefaultDestination() = 0;
};
void play_mpeg(wchar_t *m_name)
{
IUnknown *pUK=0;
IMediaControl *pMC=0;
IVideoWindow *pVW=0;
IBasicVideo *pBV=0;
IMediaSeeking *pMS=0;
CoInitialize(0);
#define CLSCTX_INPROC_SERVER 1
int hr = CoCreateInstance(&CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUK);
if(hr < 0) goto p_end;
pUK->QueryInterface(&IID_IMediaControl, (void **)&pMC);
hr = pMC->RenderFile(m_name);
if(hr < 0) goto p_end;
int vid_Width,vid_Height;
pUK->QueryInterface(&IID_IBasicVideo, (void **)&pBV);
pBV->GetVideoSize(&vid_Width, &vid_Height);
pUK->QueryInterface(&IID_IVideoWindow, (void **)&pVW);
pVW->put_Owner(0);
pVW->put_WindowStyle(WS_CHILD);
pVW->SetWindowPosition(100, 100, vid_Width, vid_Height);
int64 vid_len;
pUK->QueryInterface(&IID_IMediaSeeking, (void **)&pMS);
pMS->SetTimeFormat(&TIME_FORMAT_FRAME);
pMS->GetDuration(&vid_len);
y_ppoo("视频长度(秒) = ",vid_len/25, vid_len, 0, vid_len/25., 0);
pMC->Run();
Sleep(5000); //播放5秒钟
p_end:
if(pMS) pMS->Release();
if(pVW) pVW->Release();
if(pBV) pBV->Release();
if(pMC) pMC->Release();
if(pUK) pUK->Release();
CoUninitialize();
}