最简单的基于DirectShow的示例:视频播放器自定义版(一)

2015-01-25 11:38:04 · 作者: · 浏览: 16
本文记录一个简单的基于DirectShow的自定义的视频播放器。这里所说的“自定义播放器”,实际上指的是自己在Filter Graph中手动逐个添加Filter,并且连接这些Filter的后运行的播放器。这么做相对于使用RenderFile()这种“智能”创建Filter Graph的方法来说要复杂不少,但是可以让我们更加了解DirectShow的体系。
/

流程图

最简单的基于DirectShow的自定义的视频播放器的流程如下图所示。

/

该流程图中包含如下变量:
IGraphBuilder *pGraph:继承自IFilterGraph,用于构建Filter Graph。
IMediaControl *pControl:提供和播放控制有关的一些接口。
IMediaEvent *pEvent:用来处理Filter Graph发出的事件。
IBaseFilter *pF_source:源Filter。
IFileSourceFilter* pFileSource:源Filter的暴露的接口,用于设置输入文件的路径。
IBaseFilter *pF_demuxer:解复用Filter。
IBaseFilter *pF_decoder:解码Filter。
IBaseFilter *pF_render:渲染Filter。
IPin *pOut:输出Pin。
IPin *pIn:输入Pin。
IPin **pPin:内部变量Pin。
该流程图大体上可以分成以下步骤:
(1) 初始化DirectShow
包括以下几个步骤:
a) CoInitialize():初始化COM运行环境。
b) CoCreateInstance(…,pGraph):用指定的类标识符创建一个Com对象。在这里创建IGraphBuilder。
c) pGraph->QueryInterface(…,pControl):通过QueryInterface()查询某个 组件是否支持某个特定的接口。在这里查询IMediaControl接口。
d) pGraph->QueryInterface(…,pEvent):同上。在这里查询IMediaEvent接口。
(2) 添加Source Filter
包括以下几个步骤:
a) CoCreateInstance(…,pF_source):创建Source Filter。
b) pGraph->AddFilter(pF_source,…):将Source Filter加入Filter Graph。
c) pF_source->QueryInterface(…,pFileSource):查找Source Filter的IFileSourceFilter接口。
d) pFileSource->Load(Lxxx.mpg,pF_source):调用IFileSourceFilter的Load()方法加载视频文件。
(3) 添加Demuxer Filter
包括以下几个步骤:
a) CoCreateInstance(…,pF_demuxer):创建Demuxer Filter。
b) pGraph->AddFilter(pF_demuxer,…):将Demuxer Filter加入Filter Graph。
(4) 添加Decoder Filter
包括以下几个步骤:
a) CoCreateInstance(…,pF_decoder):创建Decoder Filter。
b) pGraph->AddFilter(pF_decoder,…):将Decoder Filter加入Filter Graph。
(5) 添加Render Filter
包括以下几个步骤:
a) CoCreateInstance(…,pF_render):创建Render Filter。
b) pGraph->AddFilter(pF_render,…):将Render Filter加入Filter Graph。
(6) 连接Source Filter和Demuxer Filter
调用了一个函数connect_filters()用于连接2个Filter。
connect_filters()的执行步骤如下:
a) 调用get_unconnected_pin()从源Filter中选择一个没有链接的输出Pin。
b) 调用get_unconnected_pin()从目的Filter中选择一个没有链接的输入Pin。
c) 连接这两个Pin
get_unconnected_pin()的执行步骤如下:
a) 枚举Filter上的Pin。
b) 遍历这些Pin,查找符合输出方向(通过IPin的QueryDirection()方法),而且没有在使用的Pin(通过IPin的ConnectedTo()方法)。
(7) 连接Demuxer Filter和Decoder Filter
过程同上。
(8) 连接Decoder Filter和Render Filter
过程同上。
(9) 开始播放
包括以下步骤:
pControl->Run():开始运行Filter Graph中的所有Filter。
pEvent->WaitForCompletion():等待Filter Graph处理完所有数据。

上述步骤可以理解为在GraphEdit软件中分别按照步骤添加以下控件。其中(1)、(2)、(3)、(4)为先添加的4个Filter,(5)、(6)、(7)为Filter之间的连接线。

/

?

源代码

/**
 * 最简单的基于DirectShow的视频播放器(Custom)
 * Simplest DirectShow Player (Custom)
 *
 * 雷霄骅 Lei Xiaohua
 * leixiaohua1020@126.com
 * 中国传媒大学/数字电视技术
 * Communication University of China / Digital TV Technology
 * http://blog.csdn.net/leixiaohua1020
 *
 * 本程序是一个简单的基于DirectShow的视频播放器。该播放器通过逐个添加
 * 滤镜并连接这些滤镜实现了视频的播放。适合初学者学习DirectShow。
 * 
 * This software is a simple video player based on DirectShow.
 * It Add DirectShow Filter Manually and Link the Pins of these filters
 * to play videos.Suitable for the beginner of DirectShow.
 */

#include stdafx.h
#include 
  
   
//'1':Add filters manually
//'0':Add filters automatically
#define ADD_MANUAL 1

//Find unconnect pins
HRESULT get_unconnected_pin(
	IBaseFilter *pFilter, // Pointer to the filter.
	PIN_DIRECTION PinDir, // Direction of the pin to find.
	IPin **ppPin) // Receives a poin