转载 自 : http://blog.csdn.net/wuanshi5/article/details/50392111

最主要的开发资料还是在 : http://blog.csdn.net/shaqoneal/article/category/1887469

总结: 不能播放mp4文件,还是因为缺少相应的库

主要用graphedit 打开视频文件,就能看到所用到的filters,如果打不开可以使用 lavfilter /  ffdshow 等解码器和解复用器

1、初始化 com, 调用CoInitialize(NULL)

2、初始化GraphBuilder, 调用CoCreateInstance。  GraphBuilder是DirectShow中视频的管理类。 非常重要。

3、枚举需要的接口,调用QueryInterface, 常用的有IID_IMediaControl、IID_IVideoWindow等。

4、创建自己需要的Filter(若是播放AVI,则可以略过这一步), 这一步需要分别创建:

分离器: 从磁盘中读取文件,并将视频文件内容分为音频流和视频流。

视频解码器: 将视频流解码为一帧一帧的画面,之后传给视频渲染器。

音频解码器: 将音频流解码为音频设备可播放的形式,之后传给音频播放设备。

视频渲染器: 负责渲染视频画面。

音频渲染器:负责播放声音。

然后,需要将各filter的pin链接起来。形成一个通畅的视频流。之后,输入文件后,DirectShow就会按照事先设定好的线路运转。

5、枚举IID_IFileSourceFilter接口,读取文件。 之后使用MediaControl对视频的播放进行控制。

这个过程需要,预先安装好对应的解码器和分离器。 渲染器系统提供了。 lav filter包含同时分离器和解码器。

我用的是,lav的分离器 lav splitter filter 和 ffdshow的解码器。

同时,如果希望直观的了解这个通路的建立过程,可以使用graphstudionext。

不过,如果希望看到程序的播放通路。需要将graphBuilder加入到ROT(对象活动表)中,具体过程参照MSDN。

参考博客: http://blog.csdn.net/shaqoneal/article/category/1887469

这个博客,详细的介绍了上述的过程。

//===================================================================================

6、使用Lav Filter手动建立Filter Graph并播放视频文件

在前面的这篇博文中,我们开始利用的手动建立Filter Graph,已经完成了Splitter Source Filter和Audio/Video Decoder的建立和链接。接下来需要做的是渲染解码完成的音视频数据,分别由Audio Render和Video Render完成。音频渲染器较为简单也很少会出问题,我们主要讨论视频渲染器的问题。

DirectShow所提供的视频渲染器种类有多种,如Video Renderer(已不常用)、VMR-7、VMR-9、EVR等。MSDN的文档讲了各种视频渲染器的相关知识。其中提到了“在vista之后的windows版本中,如果硬件支持应使用EVR”,既然已经是win 7了,那自然是首选EVR了。这部分的代码如下:

[cpp] view plain copy  
  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. //......
  4. hr = AddFilterByCLSID(pGraph,CLSID_LavSplitter_Source,L"Lav Splitter Source",&pLavSplitterSource);
  5. hr = pLavSplitterSource->QueryInterface(IID_IFileSourceFilter,(void **)&pFileSourceFilter);
  6. hr = pFileSourceFilter->Load(fileName,NULL);//必须loadfile后才能检索pin
  7. hr = AddFilterByCLSID(pGraph,CLSID_LavVideoDecoder,L"Lav Video Decoder",&pLavVideoDecoder);
  8. hr = ConnectFilters(pGraph,pLavSplitterSource,pLavVideoDecoder);
  9. hr = AddFilterByCLSID(pGraph,CLSID_LavAudioDecoder,L"Lav Audio Decoder",&pLavAudioDecoder);
  10. hr = ConnectFilters(pGraph,pLavSplitterSource,pLavAudioDecoder);
  11. hr = AddFilterByCLSID(pGraph,CLSID_EnhancedVideoRenderer,L"Enhanced Video Renderer",&pRenderer);
  12. hr = ConnectFilters(pGraph,pLavVideoDecoder,pRenderer);
  13. hr = AddFilterByCLSID(pGraph,CLSID_AudioRender,L"Audio render",&pAudioRender);
  14. hr = ConnectFilters(pGraph,pLavAudioDecoder,pAudioRender);
  15. //......
  16. }

Build工程后运行,使用GraphStudioNext查看生成的Filter Graph,可以看到音视频渲染器都已经成功加入了,如下图所示:

但是我们发现一个问题,电影已经正常播放,但是只有声音却没有图像,这是为何?

通过搜索得知,DirectShow的渲染器定义了两种模式:窗口模式和非窗口模式。窗口模式下,视频渲染器会自动生成一个视频播放窗口,渲染完成的画面会显示在这个视频窗口中;当然我们可以获取这个窗口的句柄进行下一步操作比如讲该窗口置于我们自定义的应用窗口下加以控制。非窗口模式下,视频渲染器需要指定一个视频输出窗口,将数据渲染在该窗口中。在这两种模式中,Video Renderer只支持窗口模式,VMR-7/9支持两种模式,默认为窗口模式。而在MSDN文档中指出,EVR并不支持窗口模式,显示窗口必须由应用程序自己创建。而我们的demo只是一个控制台程序,不存在窗口,自然也就无法渲染视频了。

既然不支持,那我们就换掉,改为使用VMR-9进行绘制。方法很简单,在添加EVR组件的语句中将CLSID_EnhancedVideoRenderer改为CLSID_VideoMixingRenderer9就可以了。

编译链接运行,查看Filter Graph,如下图:

播放画面:

至此,我们已经成功地把一部主流格式的电影文件通过手动建立Filter Graph的方式播放出来了,也对DirectShow的基本概念有了一定的了解。接下来还将继续进一步深入研究与其相关的更多内容。

下载该demo点这里

//=====================================================

一个基于LavFilter的对话框视频播放器

在实现了利用控制台程序播放指定视频文件之后,接下来开始尝试编写一个带有界面的视频播放器,可以选择播放的视频,控制音量等更多的功能。为简单起见,界面的框架用MFC实现。

1、建立工程,生成默认界面

这一步很简单,打开Visual Studio 2010,选择MFC Application,选择基于对话框的工程然后一路next就完成了,没有任何需要更改的地方。之后可以编译运行,生成一个默认的对话框。对工程进行与DirectShow相关的设置,具体方法参考这里。

2、添加播放器内核类

将上文中的DirectShowApi.h+.cpp文件添加到新的工程中,代码如下。

[cpp] view plaincopy
  1. <span style="font-size: 14px;"><span style="font-family:SimSun;">//DirectShowApi.h
  2. #pragma once
  3. #include <DShow.h>
  4. #include <assert.h>
  5. HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister);
  6. void RemoveFromRot(DWORD pdwRegister);
  7. HRESULT AddFilterByCLSID(IGraphBuilder *pGraph, const GUID& clsid, LPCWCHAR wszName, IBaseFilter **ppF);
  8. HRESULT GetUnconectedPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin);
  9. HRESULT ConnectFilters(IGraphBuilder *pGraph, IPin *pOut, IBaseFilter *pDest);
  10. HRESULT ConnectFilters( IGraphBuilder *pGraph, IBaseFilter *pSrc, IBaseFilter *pDest);
  11. //DirectShowApi.cpp
  12. #include "stdafx.h"
  13. #include "DirectShowAPI.h"
  14. HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
  15. {
  16. IMoniker * pMoniker = NULL;
  17. IRunningObjectTable *pROT = NULL;
  18. if (FAILED(GetRunningObjectTable(0, &pROT)))
  19. {
  20. return E_FAIL;
  21. }
  22. const size_t STRING_LENGTH = 256;
  23. WCHAR wsz[STRING_LENGTH];
  24. StringCchPrintfW(
  25. wsz, STRING_LENGTH,
  26. L"FilterGraph %08x pid %08x",
  27. (DWORD_PTR)pUnkGraph,
  28. GetCurrentProcessId()
  29. );
  30. HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
  31. if (SUCCEEDED(hr))
  32. {
  33. hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
  34. pMoniker, pdwRegister);
  35. pMoniker->Release();
  36. }
  37. pROT->Release();
  38. return hr;
  39. }
  40. void RemoveFromRot(DWORD pdwRegister)
  41. {
  42. IRunningObjectTable *pROT = NULL;
  43. if(SUCCEEDED(GetRunningObjectTable(0,&pROT)))
  44. {
  45. pROT->Revoke(pdwRegister);
  46. pROT->Release();
  47. }
  48. }
  49. HRESULT AddFilterByCLSID( IGraphBuilder *pGraph, const GUID& clsid, LPCWCHAR wszName, IBaseFilter **ppF )
  50. {
  51. if (!pGraph || !ppF)
  52. return E_POINTER;
  53. *ppF = 0;
  54. IBaseFilter *pF = 0;
  55. HRESULT hr = CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<void**>(&pF));
  56. if (SUCCEEDED(hr))
  57. {
  58. hr = pGraph->AddFilter(pF, wszName);
  59. if (SUCCEEDED(hr))
  60. *ppF = pF;
  61. else
  62. pF->Release();
  63. }
  64. return hr;
  65. }
  66. HRESULT GetUnconectedPin( IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin )
  67. {
  68. *ppPin = 0;
  69. IEnumPins *pEnum = 0;
  70. IPin *pPin = 0;
  71. HRESULT hr = pFilter->EnumPins(&pEnum);
  72. if (FAILED(hr))
  73. {
  74. return hr;
  75. }
  76. hr = pEnum->Reset();
  77. while (pEnum->Next(1,&pPin,NULL) == S_OK)
  78. {
  79. PIN_DIRECTION ThisPinDirection;
  80. pPin->QueryDirection(&ThisPinDirection);
  81. if (ThisPinDirection == PinDir)
  82. {
  83. IPin *pTemp = 0;
  84. hr = pPin->ConnectedTo(&pTemp);
  85. if (SUCCEEDED(hr))
  86. {
  87. //当前pin已经连接,无效;
  88. pTemp->Release();
  89. }
  90. else
  91. {
  92. pEnum->Release();
  93. *ppPin = pPin;
  94. return S_OK;
  95. }
  96. }
  97. pPin->Release();
  98. }
  99. pEnum->Release();
  100. return E_FAIL;
  101. }
  102. HRESULT ConnectFilters( IGraphBuilder *pGraph, IPin *pOut, IBaseFilter *pDest )
  103. {
  104. if ((pGraph == NULL)||(pOut == NULL)||(pDest == NULL))
  105. return E_POINTER;
  106. #ifdef _DEBUG
  107. PIN_DIRECTION PinDir;
  108. pOut->QueryDirection(&PinDir);
  109. assert(PinDir == PINDIR_OUTPUT);
  110. #endif // _DEBUG
  111. //得到下级filter的输入pin
  112. IPin *pIn = 0;
  113. HRESULT hr = GetUnconectedPin(pDest,PINDIR_INPUT,&pIn);
  114. if (FAILED(hr))
  115. return hr;
  116. hr = pGraph->Connect(pOut,pIn);
  117. pIn->Release();
  118. return hr;
  119. }
  120. HRESULT ConnectFilters( IGraphBuilder *pGraph, IBaseFilter *pSrc, IBaseFilter *pDest)
  121. {
  122. if ((pGraph == NULL)||(pSrc == NULL)||(pDest == NULL))
  123. return E_POINTER;
  124. IPin *pOut = 0;
  125. HRESULT hr = GetUnconectedPin(pSrc,PINDIR_OUTPUT,&pOut);
  126. if (FAILED(hr))
  127. return hr;
  128. hr = ConnectFilters(pGraph,pOut,pDest);
  129. pOut->Release();
  130. return hr;
  131. }</span></span>

在工程中添加类CFilterGraph,并在定义类的头文件中添加跟Filter Graph相关的接口成员变量;随后定义创建和删除Filter Graph的方法,代码如下:

定义:

[cpp] view plaincopy
  1. <span style="font-size: 14px;"><span style="font-family:SimSun;">//Filter Graph.h
  2. #pragma once
  3. #include "DirectShowApi.h"
  4. class CFilterGraph
  5. {
  6. public:
  7. CFilterGraph(void);
  8. ~CFilterGraph(void);
  9. public:
  10. //DirectShow相关接口成员
  11. IGraphBuilder   *pGraph;        //滤波器链表管理器
  12. IMediaControl   *pMediaControl; //媒体控制接口,如run、stop、pause
  13. IMediaEventEx   *pMediaEvent;   //媒体事件接口
  14. IBasicVideo     *pBasicVideo;   //视频基本接口
  15. IBasicAudio     *pBasicAudio;   //音频基本接口
  16. IVideoWindow    *pVideoWindow;  //视频窗口接口
  17. DWORD           m_dwGraphRegister;
  18. public:
  19. //CFilterGraph API
  20. virtual bool Create(void);      //生成滤波器链表管理器
  21. virtual void Release(void);     //释放所有接口
  22. private:
  23. //内部方法
  24. bool QueryInterfaces(void);
  25. };</span></span>

实现:

[cpp] view plaincopy
  1. <span style="font-size: 14px;"><span style="font-family:SimSun;">//Filter Graph.cpp
  2. #include "StdAfx.h"
  3. #include "FilterGraph.h"
  4. CFilterGraph::CFilterGraph(void)
  5. {
  6. }
  7. CFilterGraph::~CFilterGraph(void)
  8. {
  9. }
  10. bool CFilterGraph::Create( void )
  11. {
  12. if (!pGraph)
  13. {
  14. if (SUCCEEDED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph)))
  15. {
  16. ::AddToRot(pGraph,&m_dwGraphRegister);
  17. return QueryInterfaces();
  18. }
  19. }
  20. return false;
  21. }
  22. bool CFilterGraph::QueryInterfaces( void )
  23. {
  24. if (pGraph)
  25. {
  26. HRESULT hr = NOERROR;
  27. hr |= pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl);
  28. hr |= pGraph->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEvent);
  29. hr |= pGraph->QueryInterface(IID_IBasicVideo, (void **)&pBasicVideo);
  30. hr |= pGraph->QueryInterface(IID_IBasicAudio, (void **)&pBasicAudio);
  31. hr |= pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVideoWindow);
  32. return SUCCEEDED(hr);
  33. }
  34. return false;
  35. }
  36. void CFilterGraph::Release( void )
  37. {
  38. if (pMediaControl)
  39. {
  40. pMediaControl->Release();
  41. pMediaControl = NULL;
  42. }
  43. if (pMediaEvent)
  44. {
  45. pMediaEvent->Release();
  46. pMediaEvent = NULL;
  47. }
  48. if (pBasicVideo)
  49. {
  50. pBasicVideo->Release();
  51. pBasicVideo = NULL;
  52. }
  53. if (pBasicAudio)
  54. {
  55. pBasicAudio->Release();
  56. pBasicAudio = NULL;
  57. }
  58. if (pVideoWindow)
  59. {
  60. pVideoWindow->put_Visible(OAFALSE);
  61. pVideoWindow->put_MessageDrain((OAHWND)NULL);
  62. pVideoWindow->put_Owner(OAHWND(0));
  63. pVideoWindow->Release();
  64. pVideoWindow = NULL;
  65. }
  66. ::RemoveFromRot(m_dwGraphRegister);
  67. if (pGraph)
  68. {
  69. pGraph->Release();
  70. pGraph = NULL;
  71. }
  72. }
  73. </span></span>

现在这个类还不完整,稍后将会把这个类补全。

3、简要设计对话框的界面

在MFC默认的对话框界面中,添加一个按键用于选择视频文件,以及一个标签用于显示选定的文件名,如下图所示。

为按键添加相应函数:

[cpp] view plaincopy
  1. <span style="font-size: 14px;"><span style="font-family:SimSun;">void CLavPlayerDlg::OnBnClickedButtonSelectfile()
  2. {
  3. // TODO: Add your control notification handler code here
  4. CString strFormatFilter = _T("AVI file (*.avi)|*.avi|");
  5. strFormatFilter += _T("MPEG file (*.mpg;*.mpeg;*.mp4)|*.mpg;*.mpeg;*.mp4|");
  6. strFormatFilter += _T("HD file (*.mkv;*.ts)|*.mkv;*.ts|");
  7. strFormatFilter += _T("Audio file (*.mp3;*.aac)|*.mp3;*.aac|");
  8. strFormatFilter += _T("All file (*.*)|*.*|");
  9. CFileDialog dlg(TRUE,NULL,NULL,OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,strFormatFilter,this);
  10. if (dlg.DoModal() == IDOK)
  11. {
  12. m_VideoFilePath = dlg.GetPathName();
  13. m_VideoFileName = GetFileTitleFromFileName(m_VideoFilePath,1);
  14. CreateGraph();
  15. }
  16. }
  17. CString CLavPlayerDlg::GetFileTitleFromFileName( CString FileName, bool Ext )
  18. {
  19. int Where;
  20. Where = FileName.ReverseFind('\\');
  21. if (Where == -1)
  22. Where = FileName.ReverseFind('/');
  23. CString FileTitle = FileName.Right(FileName.GetLength() - 1 - Where);
  24. if (!Ext)
  25. {
  26. int Which = FileTitle.ReverseFind('.');
  27. if (Which != -1)
  28. FileTitle = FileTitle.Left(Which);
  29. }
  30. return FileTitle;
  31. }</span></span>

其中的m_VideoFilePath和m_VideoFileName是定义在dlg类中的两个cstring类的成员,用于接收选定视频的文件路径和文件名。CreateGraph()用于创建完整的filter graph。

[cpp] view plaincopy
  1. <span style="font-size: 14px;"><span style="font-family:SimSun;">void CLavPlayerDlg::CreateGraph()
  2. {
  3. DestroyGraph();
  4. m_pFilterGraph = new CFilterGraph();
  5. if (m_pFilterGraph->Create())
  6. {
  7. if (m_pFilterGraph->RenderFile(m_VideoFilePath))
  8. {
  9. AfxMessageBox(_T("无法播放文件,因为文件已损坏或缺少解码器!"));
  10. return;
  11. }
  12. //      m_pFilterGraph->SetDisplayWindow(m_videoWindow.GetSafeHwnd());
  13. m_pFilterGraph->SetNotifyWindow(this->GetSafeHwnd());
  14. m_pFilterGraph->Pause();
  15. }
  16. }
  17. void CLavPlayerDlg::DestroyGraph()
  18. {
  19. if (m_pFilterGraph != NULL)
  20. {
  21. m_pFilterGraph->Stop();
  22. m_pFilterGraph->SetNotifyWindow(NULL);
  23. delete m_pFilterGraph;
  24. m_pFilterGraph = NULL;
  25. }
  26. }</span></span>

播放器核心类中添加了多个函数。如Stop、Pause、SetNotifyWindow、SetDisplayWindow、RenderFile等,分别用于停止视频播放、暂停视频播放、设置通知窗口、设置显示窗口、解析播放视频文件等。下面首先考虑实现RenderFile方法。

首先需要添加头文件定义lavfilter组件的clsid,并在播放器核心类中include这个头文件:

[cpp] view plaincopy
  1. <span style="font-size: 14px;"><span style="font-family:SimSun;">//CLSID.h
  2. #pragma once
  3. #include <InitGuid.h>
  4. // {B98D13E7-55DB-4385-A33D-09FD1BA26338}
  5. static const GUID CLSID_LavSplitter_Source =
  6. { 0xB98D13E7, 0x55DB, 0x4385, { 0xA3, 0x3D, 0x09, 0xFD, 0x1B, 0xA2, 0x63, 0x38 } };
  7. //{EE30215D-164F-4A92-A4EB-9D4C13390F9F}
  8. static const GUID CLSID_LavVideoDecoder =
  9. { 0xEE30215D, 0x164F, 0x4A92, { 0xA4, 0xEB, 0x9D, 0x4C, 0x13, 0x39, 0x0F, 0x9F } };
  10. //{E8E73B6B-4CB3-44A4-BE99-4F7BCB96E491}
  11. static const GUID CLSID_LavAudioDecoder =
  12. { 0xE8E73B6B, 0x4CB3, 0x44A4, { 0xBE, 0x99, 0x4F, 0x7B, 0xCB, 0x96, 0xE4, 0x91 } };</span></span>

同时参考上篇文章中的控制台应用,在RenderFile函数中添加lavfilter的组件:

[cpp] view plaincopy
  1. <span style="font-size: 14px;"><span style="font-family:SimSun;">bool CFilterGraph::RenderFile( CString fileName )
  2. {
  3. HRESULT hr = NOERROR;
  4. LPTSTR fileToPlay = fileName.GetBuffer();
  5. hr |= ::AddFilterByCLSID(pGraph,CLSID_LavSplitter_Source,L"Lav Splitter Source",&m_pLavSplitterSource);
  6. hr |= m_pLavSplitterSource->QueryInterface(IID_IFileSourceFilter,(void **)&m_pFileSourceFilter);
  7. hr |= m_pFileSourceFilter->Load(fileToPlay,NULL);
  8. fileName.ReleaseBuffer();
  9. hr |= AddFilterByCLSID(pGraph,CLSID_LavVideoDecoder,L"Lav Video Decoder",&m_pLavVideoDecoder);
  10. hr |= ConnectFilters(pGraph,m_pLavSplitterSource,m_pLavVideoDecoder);
  11. hr |= AddFilterByCLSID(pGraph,CLSID_LavAudioDecoder,L"Lav Audio Decoder",&m_pLavAudioDecoder);
  12. hr |= ConnectFilters(pGraph,m_pLavSplitterSource,m_pLavAudioDecoder);
  13. hr |= AddFilterByCLSID(pGraph,CLSID_VideoMixingRenderer9,L"Video Mixing Renderer-9",&m_pVideoRenderer);
  14. hr |= ConnectFilters(pGraph,m_pLavVideoDecoder,m_pVideoRenderer);
  15. hr |= AddFilterByCLSID(pGraph,CLSID_AudioRender,L"Audio render",&m_pAudioRender);
  16. hr |= ConnectFilters(pGraph,m_pLavAudioDecoder,m_pAudioRender);
  17. return SUCCEEDED(hr);
  18. }</span></span>

同时在界面上新增加一个按钮,命名为“播放”,初始显示设置为FALSE,在其响应函数中调用播放内核类的run方法,使Filter Graph Manager开始运行:

[cpp] view plaincopy
  1. <span style="font-family:SimSun;">void CLavPlayerDlg::OnBnClickedBtnPlay()
  2. {
  3. // TODO: Add your control notification handler code here
  4. m_pFilterGraph->Run();
  5. }
  6. bool CFilterGraph::Run( void )
  7. {
  8. if (pGraph && pMediaControl)
  9. {
  10. if (!IsRunning())
  11. {
  12. if (SUCCEEDED(pMediaControl->Run()))
  13. {
  14. return true;
  15. }
  16. }
  17. else
  18. {
  19. return true;
  20. }
  21. }
  22. return false;
  23. }
  24. bool CFilterGraph::IsRunning( void )
  25. {
  26. if (pGraph && pMediaControl)
  27. {
  28. OAFilterState state = State_Stopped;
  29. if (SUCCEEDED(pMediaControl->GetState(10, &state)))
  30. {
  31. return state == State_Running;
  32. }
  33. }
  34. return false;
  35. }</span>

除此之外还需要在CreateGraph中添加Label显示文件名,以及显示播放按钮的功能,完成后效果如下:

[cpp] view plaincopy
  1. <span style="font-family:SimSun;">void CLavPlayerDlg::CreateGraph()
  2. {
  3. DestroyGraph();
  4. m_pFilterGraph = new CFilterGraph();
  5. if (m_pFilterGraph->Create())
  6. {
  7. if (m_pFilterGraph->RenderFile(m_VideoFilePath) == false)
  8. {
  9. AfxMessageBox(_T("无法播放文件,因为文件已损坏或缺少解码器!"));
  10. return;
  11. }
  12. m_pFilterGraph->SetNotifyWindow(this->GetSafeHwnd());
  13. m_pFilterGraph->Pause();
  14. GetDlgItem(IDC_VIDEOFILE)->SetWindowText(m_VideoFileName);
  15. GetDlgItem(IDC_BTN_PLAY)->ShowWindow(TRUE);
  16. }
  17. }</span>

编译运行,初始界面如:

选择文件后,出现“播放”按钮:

播放之后的界面:

虽然视频的播放功能已经实现但是应用却还是十分的不完善(比如没有播放控制功能,没有音量调节等),还有很多漏洞,以后会在学习的过程中逐步改进。

本文DEMO下载请点击这里

DirectShow 播放mp4编码 视频相关推荐

  1. 流媒体播放器播放h264编码视频与h265编码视频哪个更清晰?

    h265编码是h264编码的升级版,h265目前在视频点播方面使用的更加普遍,而在视频直播方面,由于难以达到h265编码的解码速度,运用起来还是有些难度的,还需要看未来我们的流媒体技术的发展.那么既然 ...

  2. Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型

    转自原文 Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型 播放mp4格式的时候提示 Html 播放 mp4格式视频提示 没有发现支持的视频格式和mime类型 原因是在IIS中 ...

  3. 解决 Ubuntu 无法播放 MP4 格式视频的问题的办法

    解决 Ubuntu22.04 无法播放 MP4 格式视频的问题的办法 问题原因:         系统中的终端上安装缺少的编解码器. 解决办法: 第一条命令将更新存储库: sudo apt-get u ...

  4. html5播放mp4不见画面,浏览器播放mp4格式视频时只有声音看不到画面的原因及解决方法(精)...

    做HTML5网页,要播放视频,视频格式为mp4,结果浏览器只能听到声音,看不到画面. 反复测试,多个浏览器均出现此问题.刚开始以为视频的格式不对,我是从MOV转的MP4格式,反复确认嵌入的视频确实是m ...

  5. 微信 html avi视频无法播放,为何MP4不能播放MP4格式视频文件

    [海龙资讯网 导购]今天早上有个朋友打电话给我说:"喂,现在的商家真是爱骗人啊~!我新买的MP4都不能播放mp4格式的视频."小编我看到这个问题确实也是有点小囧.从正确的命名方法来 ...

  6. 旧版RTSP协议网页视频无插件直播EasyNVR视频平台为什么无法播放H264编码视频?

    RTSP协议视频平台EasyNVR经过了很多代的升级,目前已经支持H.265编码视频的播放,然而我们很多客户使用的还是旧版本的EasyNVR视频服务器软件(4.0.0之前的版本统称为旧版,均不支持H2 ...

  7. Ubuntu无法播放MP4格式视频问题的解决

    历经3天艰苦卓绝的尝试,期间直接将虚拟机玩崩了一次,今天终于是弄好了啊. 开始是按照该博主的文章,安装了FFMPEG: (1条消息) Ubuntu 18.04 安装FFmpeg_假装很坏的谦谦君的博客 ...

  8. ijkplayer 播放mpeg2video编码视频花屏

    概要 正常情况下,ijkplayer自行编译时,我们使用config/module-lite.sh配置,即可满足大部分需求. 但是该配置不支持mpeg相关的视频编码播放. 通常,我们会使用如下方式添加 ...

  9. 小程序video标签在(华为手机)无法播放.mp4长视频(ios上正常)

    问题场景 后台上传了有一个大小为700+M的视频文件,结果在小程序播放页面加载一会就会黑屏,并且视频时长也没有解析成功,但是视频路径在浏览器访问是没有问题的.(当时是在小米手机出现该bug) 分析问题 ...

最新文章

  1. r - 求平均成绩_EXCEL计算修剪平均和条件平均,其实很简单
  2. gitpythonapi_GitPython 使用基础
  3. 国内外包行业的现状分析
  4. display none 隐藏后怎么显示_Web 隐藏技术:几中隐藏 Web 中的元素方法及优缺点
  5. NTT通信公司在大阪开通运营容灾数据中心
  6. ACDU活动回顾:@DBA,前辈指路不迷茫
  7. 谷歌(Google Chrome)插件安装
  8. 19套最新的免费图标字体集
  9. python之路--面向对象之封装
  10. 使用java实现敏感词汇过滤功能
  11. 【李宏毅机器学习HW2】
  12. msdia80.dll文件出现在磁盘根目录下的解决方案
  13. 仿QQ登录界面UI设计
  14. Photoshop脚本 删除当前图层
  15. 采用MCaaS模式 SAP为有孚网络提供基于HANA的解决方案及服务
  16. 移动支付清算平台介绍
  17. 利用java对接阿里云sls服务(aliyun-log)做浏览记录
  18. Nginx编译时error: assignment makes pointer from integer without a cast处理
  19. 如何用日志记录VSS中的用户修改行为
  20. 计算机怎么知道乘法优先,计算器算个明白.doc

热门文章

  1. 匝间短路故障学习历程(四) -- 频谱分析
  2. 最后的晚餐中的秘密?----《达芬奇密码》读后
  3. EFM32 LEUART
  4. 微信小程序媒体组件-image图片懒加载效果
  5. win8英文版安装SQLserver2012英文版图文教程
  6. 薪酬管理系统(java)
  7. javaweb物流信息发布管理平台
  8. 自制Jlink_OB(STM32c8t6)
  9. 电气自动化专业里的计算机知识,为什么说千万别学电气自动化?哪些人适合学电气自动化?...
  10. OpenID使用方法