visual c++ 音频视频处理技术及工程实践

来源:互联网 发布:中兴n760软件下载 编辑:程序博客网 时间:2024/06/05 02:44
 

10.19

这里我写好了界面,但我不知道8.2节具体是做什么工作的,所以我跳过了

8.2,首先创建一个最简单的媒体播放器。

 

8.3 我所做的工作步骤是:

        1:给打开按钮添加了事件响应函数

    2:在BOOL CMediaPlayerApp::InitInstance()里添加了//初始化COM

         CoInitialize(NULL);

                   3:我将code里的打开的事件响应函数的代码复制到我了我的工程里面。

 

#if 1

         CString strFilter = _T("AVI File (*.avi) | *.avi|");

         strFilter += "MPEG File (*.mpg; *.mpeg) | *.mpg; *.mpeg|";

         strFilter += "MP3 File (*.mp3) | *.mp3|";

         strFilter += "WMA File (*.wma) | *.wma|";

         strFilter += "All File (*.*) | *.*|";

#else

         CString strFilter = _T("AVI File (*.avi)|*.avi|MPEG File (*.mpg)|*.mpg|MP3 File (*.mp3)|*.mp3|All Files (*.*)|*.*||");

#endif

 

 

         CFileDialog dlg(TRUE, NULL, NULL, OFN_PATHMUSTEXIST|OFN_HIDEREADONLY, strFilter, this);

         if (dlg.DoModal() == IDOK)

         {

                   m_sourceFile = dlg.GetPathName();

                   m_mediaFileName =GetFileTitleFromFileName(m_sourceFile,1);

 

                   CreateGraph();

         }       

 

这里有几个问题,1:这里和书中的代码不一样。

                                      2:编译一样有下面的错误

mediaplayerdlg.cpp(172) : error C2065: 'm_sourceFile' : undeclared identifier

mediaplayerdlg.cpp(173) : error C2065: 'm_mediaFileName' : undeclared identifier

mediaplayerdlg.cpp(173) : error C3861: 'GetFileTitleFromFileName': identifier not found

mediaplayerdlg.cpp(175) : error C3861: 'CreateGraph': identifier not found

 

第一二个错误好解决,我的解决方法是。m_sourceFile  m_mediaFileName 实际上是CMediaPlayerDlg类的两个成员变量,加进去就可以。

public:

         CString     m_sourceFile;  //  m_sourceFile 表示的是媒体的路径

         CString  m_mediaFileName;  //  m_mediaFileName 表示是的媒体的文件名。

GetFileTitleFromFileName 完成的功能是从路径中获取多媒体文件的名称。这个函数在MSDN没有找到, 我姑计是作者自己写的一个函数。

CreateGraph 完成的功能是创建链表,连接滤波器。这个函数在MSDN没有找到,我姑计是作者自己写的一个函数。

 

基于此,我是这样办的。

首先处理GetFileTitleFromFileName  我在MediaPlayerDlg.h : 头文件里添加了代码

public:

         CString  GetFileTitleFromFileName(CString FileName, BOOL Ext);

 

然后在MediaPlayerDlg.cpp文件里添加了这个函数的实现。

CString CMediaPlayerDlg::GetFileTitleFromFileName(CString FileName, BOOL Ext)  

{  

    int Where;  

    Where = FileName.ReverseFind('\\'); 

    if (Where == -1) 

        Where = FileName.ReverseFind('/'); 

    CString FileTitle = FileName.Right(FileName.GetLength() - 1 - Where); 

    if (!Ext) 

    { 

        int Which = FileTitle.ReverseFind('.');  

        if (Which != -1)  

            FileTitle = FileTitle.Left(Which);  

    }  

    return FileTitle;  

}  //  我记得应该有三个地方要改的,可是我找不到地方,这里我就不管了,反正编译只有一个错误了。

 

接着处理CreateGraph :

我按照我先前的做法void CreateGraph(); void DestroyGraph(); 两个函数,可是我却发现了好多的错误。我都快晕了。

mediaplayerdlg.cpp(204) : error C2065: 'm_pFilterGraph' : undeclared identifier

mediaplayerdlg.cpp(204) : error C2061: syntax error : identifier 'CDXGraph'

mediaplayerdlg.cpp(205) : error C2227: left of '->Create' must point to class/struct/union/generic type  type is ''unknown-type''

mediaplayerdlg.cpp(210) : error C2227: left of '->RenderFile' must point to class/struct/union/generic type  type is ''unknown-type''

mediaplayerdlg.cpp(217) : error C2227: left of '->SetDisplayWindow' must point to class/struct/union/generic type  type is ''unknown-type''

mediaplayerdlg.cpp(217) : error C2065: 'm_videoWindow' : undeclared identifier

mediaplayerdlg.cpp(217) : error C2228: left of '.GetSafeHwnd' must have class/struct/union

   type is ''unknown-type''

mediaplayerdlg.cpp(219) : error C2227: left of '->SetNotifyWindow' must point to class/struct/union/generic type   type is ''unknown-type''

mediaplayerdlg.cpp(221) : error C2227: left of '->Pause' must point to class/struct/union/generic type  type is ''unknown-type''

mediaplayerdlg.cpp(231) : error C2227: left of '->Stop' must point to class/struct/union/generic type   type is ''unknown-type''

mediaplayerdlg.cpp(232) : error C2227: left of '->SetNotifyWindow' must point to class/struct/union/generic type  type is ''unknown-type''

mediaplayerdlg.cpp(234) : error C2541: 'delete' : cannot delete objects that are not pointers

 

我觉得我应该是没有添加CDXGraph这个类,所以我加了上去。并在CMediaPlayerDlg 类的头文件里加了#include "CDXGraph.h" 还是有很多错误,没办法,还得一个一个。

 

经过纠结 我只是没有添加几个变量,添加一下就可以了,CStatic m_videoWindow; CDXGraph *m_pFilterGraph;  # pragma comment (lib , "strmiids.lib") 加了这里基本上就没有错了,呵呵,

 

4:接着我给PLAY按钮增加响应函数。并添加代码。

if (m_pFilterGraph)

         {

                   SetWindowText(_T("1倍速播放") + m_mediaFileName);

                   m_pFilterGraph->Run();

                   //m_volume = m_pFilterGraph->GetAudioVolume();

                   //m_sliderAudio.SetPos(m_volume);

                   //m_volume = 100;

                   m_pFilterGraph->ChangeAudioVolume(m_volume);

                   m_sliderVolume.SetPos(m_volume);

 

                   if (m_playerTimer == 0)

                   {

                            m_playerTimer = SetTimer(SLIDER_TIMER, 100, NULL);

                   } // 在这里我把这部代码注释,发可以放了,

         }

 

但是有小问题,1:图像初始化的时候不显示在图像控件上。

               2:视频很小。

实然,我感觉这个错误是我在生成窗口的时间,点一个叫什么框架的东西,于是,我打算重来一遍。 

如果设置是

结果是这个窗口在桌面的左顶上角,且停在最小化状态。

如果选择是这样的。

这时编译窗口显示正常,且开始显示在中间。

 

 

 

 

 

 

 

如果不要thick frame 选项,结果跟第二个是一样的。

 

综上,我选择只要MAX BOX   MIN BOX两个选择。(下面的工程设计都是这样的,希望不会错。)  这里我再时间去纠结代码。

 

经过我再一次实验,发现不是我刚刚发现的错误。现象依旧,怎么办,我还没有吃饭!!!。

 

10.20.2011

继续昨天的工作 , 我又发现,很可能跟位图和图像控件有关系,于是,我去找找线索。

找了没有线索。

 

我突然发现是不是有一个函数可以将坐标进行转换的。

public:

         afx_msg BOOL OnEraseBkgnd(CDC* pDC); 于是我找到了它,现在试一下。

唉也不是,

 

 

于是我只能接着往前走了,不管这个问题。上面的代码我没有注释,因为好像对程序没有什么影响。

 

昨天有一个问题就是在按键PLAY里面有一段代码不知道是什么意思 。我这里把它加进去,

 

终于找到视频显示在顶端的原因了。

m_videoWindow 是图像控件变量,我没有将它和控件相关联,而仅仅是添加这个成员变量。唉控件变量。

 

m_sliderPlayer m_sliderVolume 这两个也是控件变量。

 

         当我加进play按钮代码发现了很多问题。比如在对话框初始化的时候,有这么些代码是我没有注意到的。

// TODO: Add extra initialization here

 

         m_pFilterGraph = NULL;

 

         m_sliderPlayer.SetRange(0, 1000);

         m_sliderPlayer.SetPos(0);

 

         m_sliderVolume.SetRange(50,100);

         m_sliderVolume.SetPos(50);

         m_volume = 100;

 

这应该很重要。另外我给函数添加了两个消息。一个是WM_TIMER消息,另一个是WM_HSCROLL 消息。完成滚动条滚动时控制的命令。

 

接下来,给STOP按钮添加命令响应消息。 添加下面的代码

         if (m_pFilterGraph != NULL)

         {

                   m_pFilterGraph->Stop();

         }

 

给暂停添加命令响应消息。添加下面的代码。

if (m_pFilterGraph != NULL)

         {

                   m_pFilterGraph->Pause();

         }

 

给退出添加命令响应消息。添加下面的代码。

OnBnClickedButtonStop();

         CoUninitialize();

 

         CDialog::OnOK();

 

给抓图添加命令响应消息。添加下面的代码。

static int c = 0;

         TCHAR szFilename[MAX_PATH];

         DWORD   dwPathLen  = 0;  

         if((dwPathLen = ::GetModuleFileName(::AfxGetInstanceHandle(),szFilename, MAX_PATH ))== 0)

         {  

                   return;  

         }  

         for( int i=dwPathLen-1;  i>=0; i--)

         {  

                   if(('\\' == szFilename[i])  ||  ('/' == szFilename[i]))

                   {  

                            break;  

                   } else {  

                            szFilename[i]   =   '\0';  

                   }  

         }  

        

         CString str;

         str.Format(_T("%s"),szFilename);

 

         CString strTemp;

         strTemp.Format(_T("%d"),c);

         str += strTemp + _T(".bmp");

         c++;

        

         TCHAR *p=str.GetBuffer(str.GetLength());

         str.ReleaseBuffer();

 

         if (m_pFilterGraph != NULL)

         {

                   if (m_pFilterGraph->SnapshotBitmap(p))

                   {

                   }else

                            MessageBox(_T("抓图失败!"));

         }

 

这里我注意到,图片被保存到工程目录下,。但当我抓图完成后。播放器界面就会显示最开始的位图,只有当窗口重绘时才会显示动态的影像。这里应该是要对图像进行窗口重绘。这个工作我打算最后做。这里在书的P328面有说明 ,不全是我先前想的那样。这里提供了另一种方法。 当然,在窗口切换时还是会有不能正常显示的现象。

 

至此,我已经完成了一个小小的视频播放器了。

 

接着完成P320D面以后的工作。

 

捕获媒体播放的消息和各种事件,向窗口发送通知。

 这里按照书上做没有错。

 

接着升级我的播放器。

  为了在视频中显示窗口,单击鼠标右键激活菜单,需要我们重载窗口消息捕获处理函数PreTranslateMessage .

CToolTipCtrl m_tooltip 我不知道这是一个什么控件类型。我只能COPY

 

接着完成书中的内容,就可以实现一个播放器的功能了。

 

 

 

原创粉丝点击