1.头文件
#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 value enum 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 property typedef 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 video LONG lWidth; //Height of the video LONG lHeight; //Approximate bit rate LONG lBitRate; }MEDIAPROPERTY,*PMEDIAPROPERTY; //-------------------------------------------------------------------- class CMedia { public: HRESULT SetPositions(LONGLONG __RPC_FAR *pCurrent, DWORD dwCurrentFlags, LONGLONG __RPC_FAR *pStop, DWORD dwStopFlags); HRESULT GetPositions( LONGLONG __RPC_FAR *pCurrent,LONGLONG __RPC_FAR *pStop); HRESULT SetTimeFormat(const GUID __RPC_FAR *pFormat); HRESULT GetRate(double __RPC_FAR *pdRate); HRESULT GetDuration(LONGLONG __RPC_FAR *pDuration); HRESULT GetCurrentPosition(LONGLONG __RPC_FAR *pCurrent); HRESULT WaitForCompletion(long msTimeout, long *pEvCode); HRESULT GetState(LONG msTimeout, OAFilterState *pfs); 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(); CMedia(); protected: // Collection of interfaces IGraphBuilder *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 video //HWND m_hWndNotify; //The window notify //BOOL m_bExitThrd; //BOOL m_bThrdRunning; static CMedia *m_pInstance; DISPLAYMODE m_DispMode; };
2.类的实现
#include "stdafx.h" #include "类头文件" #include <dshow.h> #include <streams.h> #pragma comment (lib,"Ole32.lib") #pragma comment (lib,"Strmiids.lib") //---------------------------------------------------------------------------------------------- //Macro define //Default play mode #define DEFAULT_DISPLAY_MODE DISP_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_hWndNotify(NULL) m_DispMode(DEFAULT_DISPLAY_MODE) { 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 file if(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 existing HANDLE hdFile = CreateFile(m_szFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL); if(hdFile == INVALID_HANDLE_VALUE) { //The file doesn't exist goto END; } else { CloseHandle(hdFile); } } // Initialize COM if(CoInitializeEx(NULL, COINIT_MULTITHREADED) != S_OK) { goto END; } // Get the interface for DirectShow's GraphBuilder if(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB) != S_OK) { goto END; } // Have the graph construct its the appropriate graph automatically if(m_pGB->RenderFile(m_szFileName, NULL) != NOERROR) { goto END; } // QueryInterface for DirectShow interfaces if(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 files if(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 mode SetDisplayMode(m_DispMode); bResult = TRUE; END: if(bResult == FALSE) { //Release the resource Close(); } 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 hiding 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; } // Finished with COM memset(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 property m_pBA->get_Volume(&prop.lVolume); m_pBA->get_Balance(&prop.lBalance); //Get the video property if(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 mode m_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 events m_pME->FreeEventParams(evCode, evParam1, evParam2); } else { return FALSE; } return TRUE; } //---------------------------------------------------------------------- //Description: // method retrieves the state of the filter graph—paused, running, // or stopped. // //----------------------------------------------------------------------- HRESULT CMedia::GetState(LONG msTimeout, OAFilterState *pfs) { return m_pMC->GetState(msTimeout, pfs); } //---------------------------------------------------------------------- //Description: // Blocks execution of the application thread until the graph's // operation finishes. // //----------------------------------------------------------------------- HRESULT CMedia::WaitForCompletion(long msTimeout, long *pEvCode) { return m_pME->WaitForCompletion(msTimeout, pEvCode); } //------------------------------------------------------------ //Description: // get current time. // When you call the function,you should call Open() before. // //------------------------------------------------------------- HRESULT CMedia::GetCurrentPosition(LONGLONG *pCurrent) { return m_pMS->GetCurrentPosition(pCurrent); } //------------------------------------------------------------ //Description: // get all the time. // When you call the function,you should call Open() before. // //------------------------------------------------------------- HRESULT CMedia::GetDuration(LONGLONG *pDuration) { return m_pMS->GetDuration(pDuration); } //------------------------------------------------------------ //Description: // get rate. // When you call the function,you should call Open() before. // //------------------------------------------------------------- HRESULT CMedia::GetRate(double *pdRate) { return m_pMS->GetRate(pdRate); } //------------------------------------------------------------ //Description: // set time format // When you call the function,you should call Open() before. // //------------------------------------------------------------- HRESULT CMedia::SetTimeFormat(const GUID *pFormat) { return m_pMS->SetTimeFormat(pFormat); } HRESULT CMedia::GetPositions(LONGLONG *pCurrent, LONGLONG *pStop) { return m_pMS->GetPositions(pCurrent, pStop); } HRESULT CMedia::SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags) { return m_pMS->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags); }