上一个博客我写了做视频播放器的环境搭建,没写完这个项目,所以今天在把它详细的写一遍流程,介绍一下这个项目的编写。
1.需求分析;要求开发播放器系统能够播放媒体文件,而且还可以进行播放速度的控制、屏控制、音量控制、顶部显示、和抓图存盘的功能。
2.开发环境: 在windows10上使用集成开发工具Microsoft Visual Stdio 2013.以及DirectShow SDK的使用。
3.设计FilterGraph结构,这个过程就是提前调试媒体播放功能。这个过程是可以省去的,但是我们可以看一下是如何使用Filter来播放一个AVI视频文件。具体的流程如下所示:
(1) 从一个源Filter文件读取数据,并形成字节流。
(2) 检查AVI数据流的头格式,使用专用的AVI分割Filter,将视频流和音频流分开。
(3) 解码视频流,根据压缩格式的不同,选取不同的Decoder Filters.
(4) 通过Renderer Filter重画视频图像。
(5) 使用DirectSound Device Filter 将音频流送到声卡并且进行播放。
4.具体编码
4.1 定义一个类 CDXGraph 封装了和 DirectShow 有关的接口和方法,此类在文件CDXGraph.cpp里面实现,头文件文CDXGraph.h.
class CDXGraph
{
//private:
public:
IGraphBuilder *pGraph; //滤波器链表管理器
IMediaControl *pMediaControl; //媒体控制接口,如run、stop、pause
IMediaEventEx *pMediaEvent; //媒体事件接口
IBasicVideo *pBasicVideo; //视频基本接口
IBasicAudio *pBasicAudio; //音频基本接口
IVideoWindow *pVideoWindow; //视频窗口接口
IMediaSeeking *pMediaSeeking; //媒体定位接口
DWORD mObjectTableEntry;
public:
CDXGraph();
virtual ~CDXGraph();
public:
virtual bool Create(void); //生成滤波器链表管理器
virtual void Release(void); //释放所有接口
virtual bool Attach(IGraphBuilder * inGraphBuilder);
//IGraphBuilder * GetGraph(void); //Not outstanding reference count
IMediaEventEx * GetEventHandle(void); //返回IMediaEventEx指针
//根据引脚方向连接滤波器
bool ConnectFilters(IPin * inOutputPin, IPin * inInputPin, const AM_MEDIA_TYPE * inMediaType = 0);
//断开连接滤波器
void DisconnectFilters(IPin * inOutputPin);
//设置显示窗口
bool SetDisplayWindow(HWND inWindow);
//设置窗口通知消息
bool SetNotifyWindow(HWND inWindow);
//窗口大小改变处理函数
bool ResizeVideoWindow(long inLeft, long inTop, long inWidth, long inHeight);
//处理事件
void HandleEvent(WPARAM inWParam, LPARAM inLParam);
//媒体运行状态
bool Run(void); // Control filter graph
bool Stop(void);
bool Pause(void);
bool IsRunning(void); // Filter graph status
bool IsStopped(void);
bool IsPaused(void);
//设置显示窗口全屏显示
bool SetFullScreen(BOOL inEnabled);
bool GetFullScreen(void);
// 媒体定位
bool GetCurrentPosition(double * outPosition);
bool GetStopPosition(double * outPosition);
bool SetCurrentPosition(double inPosition);
bool SetStartStopPosition(double inStart, double inStop);
bool GetDuration(double * outDuration);
bool SetPlaybackRate(double inRate);
//设置媒体音量: range from -10000 to 0, and 0 is FULL_VOLUME.
bool SetAudioVolume(long inVolume);
long GetAudioVolume(void);
//设置音频平衡: range from -10000(left) to 10000(right), and 0 is both.
bool SetAudioBalance(long inBalance);
long GetAudioBalance(void);
//剖析媒体文件
//bool RenderFile(char * inFile);
bool RenderFile(TCHAR * inFile);
//抓图
bool SnapshotBitmap(TCHAR *outFile);//const char * outFile);
int m_nVolume;
void ChangeAudioVolume(int nVolume);
//静音开关
void Mute();
void UnMute();
private:
//供GraphEdit调试时使用
void AddToObjectTable(void) ;
void RemoveFromObjectTable(void);
//查询有关接口
bool QueryInterfaces(void);
};
在这个头文件中的类,定义了Graph滤波器链表,设计了图像窗口、媒体播放控制(运行 、暂停、停止)、视频的全屏显示、抓图保存等功能
4.2播放控制
(1) 打开媒体控制、渲染媒体控制、播放媒体文件、实现控制功能、实现拖放功能、实现音量调节、添加背景图片。
上述播放功能是通过是鼠标单击菜单或者播放按钮的事件处理机制实现的。在windows操作系统里面,专门有一个线程在监控系统的消息队列,并将消息分发到各应用程序的消息队列,最后,应用程序对各自的消息进行检索处理。
最终实现的界面如下: