norains的专栏

只专注于WINCE开发

用户操作
[即时聊天] [发私信] [加为好友]
norains
norains的公告
联系方式请看置顶文章
最近评论
dfdf:讨厌MFC!我觉得MFC就是太乱了!看似无用的代码不要不行,MD微软啥都给我们做完了,原理性的东西我们却永远没法搞懂了!
ironox:有个地方 我觉得很别扭,不知道怎么办好

比如说 CReg reg(HKEY_CURRENT_USER,TEXT("ControlPanel\Volume"));
ControlPanel\Volume 有可能不存在呀,这个该怎么处理哦?对象虽然创建了,出错了也没提示
szterry:呵呵,果然工作狂技术狂,同感,一样的感觉……不过我才刚毕业一年……搞IT就是玩……
jinlking:这个botton的实现只是在主窗口画了一块区域,对于事件的处理还要放在主窗口的窗口处理函数之中,在对应的消息处理上调用CheckTap来判断是否是此“按钮”,问一下,这种方法与把按钮封装在子窗口中有什么区别,二者使用那个更好?
KUODY:博主真是好人
文章分类
收藏
    相册
    动漫
    文章图片
    程序交流
    xumercury的BLOG
    狗友们的博客
    清蒸石斑鱼
    美女如刀锋
    茁茁的BLOG
    魅力老姐的窝
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 wince下用DirectShow播放音频和视频收藏

    新一篇: 一个简单的带消息循环的控制面板选项例程 | 旧一篇: WinCE工作区和任务栏

    //========================================================================
    //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:消息的参数.
           
           
            那么,现在以接收一个视频播放结束事件的代码片段为例子:
            //自定义一个消息
            #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 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, (