LAVFilter是一套著名的DirectShow插件,包括Demux,Video Decoder,AudioDecoder,播放文件所需要的几个重要插件都包含进去了,并且支持播放的视音频格式非常广泛,FFmpeg支持的它几乎都支持(因为它底层是调用FFmpeg)。LAVFilter是我们开发Directshow播放器必不可少的插件,值的一提的是它既支持软解又支持硬解,功能非常强大。在Vista以上系统硬解的时候渲染器必须要用EVR,很多关于directshow播放器的例子都是解码器连接VMR进行播放的,连接EVR的很少介绍,这篇文章就给大家讲一下怎么用LAV + EVR来播放视频。
假如我们要播放一个视频文件,那么用Directshow需要构建一个Filter链路图,以下就是播放一个文件的链路图例子:
上图连接的渲染器是Video Renderer(VMR),但是如果要切换到硬解模式,则连接的渲染器要改成EVR(enhanced video renderer)。
我写了一个类,封装了构建和运行DirectShow FilterGraph的一些流程,下面是类的声明:
// CHDVideoPlayGraph
class CHDVideoPlayGraph : public CWnd
{
DECLARE_DYNAMIC(CHDVideoPlayGraph)
public:
CHDVideoPlayGraph();
virtual ~CHDVideoPlayGraph();
void SetNum(int num) { m_Num = num; }
HRESULT BuildGraph(LPCTSTR lpszSrcFile);
void StopCapture();
BOOL GetVideoSize(CSize & size);
PLAYSTATE GetState() { return m_psCurrent; }
BOOL GetVideoStatis(DWORD & dwBitrate, UINT & dwFps);
void UnIntializeVideo();
HRESULT InitializeVideo(HWND hWnd);
HRESULT SetupVideoWindow(HWND hVideoWnd);
void ResizeVideoWindow();
DWORD GetCurrentBitrate();
void SetVideoMediatype(AM_MEDIA_TYPE * pMt);
void SetAudioMediatype(AM_MEDIA_TYPE * pmt);
void SetCaptureCallback(VideoCaptureCB captureCB) { m_CaptureCB = captureCB; }
void CheckRgb24Buffer();
void OnRecvVideo(int nNum,PBYTE pBuffer,long BufferLen); //被回调函数调用
BOOL HasAudioStream() { return m_bHasAudio; }
void SetAudioStream(BOOL bEnable) { m_bHasAudio = bEnable; }
//void SetVideoRecvPort(int port);
LRESULT OnRestartPlaying(WPARAM wParam, LPARAM lParam);
void SetHarewareDecode(BOOL bFlag);
void SetVMRMode(int nVMR);
int GetFrameRate();
protected:
DECLARE_MESSAGE_MAP()
afx_msg HRESULT OnGraphNotify(WPARAM wp, LPARAM lp);
afx_msg void OnPaint();
void DisplayMesg(TCHAR* szFormat, ...);
LRESULT ClearInterfaces(WPARAM wp, LPARAM lp);
void CloseInterfaces();
HRESULT AddGraphToRot(IUnknown* pUnkGraph, DWORD* pdwRegister);
void RemoveGraphFromRot(DWORD pdwRegister);
HRESULT HandleGraphEvent();
HRESULT GetInterfaces();
HRESULT SetSyncClock();
void GetSyncClock();
HRESULT RenderFilter(IBaseFilter * pFilter);
private:
UINT chFullScreen, chAlwaysOnTop;
UINT m_Num;
CBrush m_empt