• wince下用directx播放音频和视频


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

            虽然网上关于wince下如何使用directx播放多媒体文件的资料不多,但WinCE毕竟还属于windows,而桌面系统的directx例子网上信手拈来,并且其中directx的功能方法与之WinCE下差别不大,又本人实在没有信心比他们的轮子造得更为华丽,所以这篇文章就直接切入正题,不介绍directx的结构功能,直接来看看怎么用吧.(其实还是自己懒惰的原因大一些,恩,不过这个和本文的主题没多大关系:-)).
            
            为了方便代码的移植,所以我将directx的操作封装成CMedia类,只要直接调用该类,就可以相当简便地调用directx来播放多媒体文件了.
            
            好,闲话至此,我们以具体代码看看是如何:         //获取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().
            
            该函数的作用是设置一个接受消息的窗口,当directx有事件变更时,就会发送指定的消息到指定的窗口,原型如下:
            
            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;
                        
                        //获取此时的directx事件
                        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 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:
        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 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;

    };

    #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

    //----------------------------------------------------------------------
    //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)
        ...{
            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;
    }

  • 相关阅读:
    HDU--4548 美素数
    【思维】南阳理工 14 会场安排问题
    【思维】【水】 南阳oj 喷水装置(一)
    【思维】南阳理工91 阶乘之和
    【转】哈夫曼树 九度1172
    Array
    HDU--1702 ACboy needs your help again!
    栈和队列
    3.Compound data types
    4.Object Oriented Programming
  • 原文地址:https://www.cnblogs.com/googlegis/p/2979221.html
Copyright © 2020-2023  润新知