最简单的基于DirectShow的示例:获取Filter信息
=====================================================
最简单的基于DirectShow的示例文章列表:
最简单的基于DirectShow的示例:视频播放器图形界面版
最简单的基于DirectShow的示例:获取Filter信息
=====================================================
本文记录一个获取DirectShow的Filter信息的程序。该程序可以遍历当前系统中的DirectShow Filter并且将它们的信息打印到控制台中。通过本程序可以搞清楚DirectShow中Filter,Pin,MediaType等几个关键结构之间的关系,以及它们的信息的获取方法。
流程图
该程序的流程图如下所示。由于该图的尺寸比较大,在页面中显示不下,所以在相册中上传了一份:
接口
该流程图中涉及到以下接口:
ICreateDevEnum *pSysDevEnum:设备列举接口。
IEnumMoniker *pEnumCat:Moniker(别名)枚举接口。
IMoniker *pMoniker:Moniker(别名)接口。
IPropertyBag *pPropBag:存储属性值的接口。
IBaseFilter *pFilter:Filter接口。
IEnumPins * pinEnum:Filter枚举接口。
IPin * pin: Pin接口。
PIN_INFO pinInfo:存储Pin的信息的结构体。
IEnumMediaTypes *mtEnum:MediaType枚举接口。
AM_MEDIA_TYPE *mt:描述媒体类型的结构体。
流程图
该流程图中涉及到以下函数:
【初始化】
CoInitialize():初始化COM运行环境。
CoCreateInstance(…,pSysDevEnum):用指定的类标识符创建一个Com对象。在该示例中类标识符为“IID_ICreateDevEnum”,用于创建ICreateDevEnum。
【Filter的枚举】
pSysDevEnum->CreateClassEnumerator(…,pEnumCat):通过ICreateDevEnum查询IEnumMoniker枚举接口,枚举指定类型目录下的设备Moniker(别名)。
pEnumCat->Next(…,pMoniker):通过IEnumMoniker查询下一个IMoniker接口。
pMoniker->BindToStorage(…,pPropBag):通过IMoniker查询IPropertyBag接口(用于获取Filter信息)。
pPropBag->Read("FriendlyName"):通过IPropertyBag获取“FriendlyName”属性的值。pMoniker->BindToObject(…,pFilter):通过IMoniker查询IBaseFilter接口(用于获取Filter,注意和BindToStorage()区别)。
【Pin的枚举】
pFilter->EnumPins(pinEnum):通过IBaseFilter查询IEnumPins枚举接口。
pinEnum->Next(…,pin):通过IEnumPins查询下一个IPin接口。pin->QueryPinInfo(PinInfo):通过IPin获取Pin的信息。
【MediaType的枚举】
pin->EnumMediaTypes(&mtEnum):通过IPin查询IEnumMediaTypes枚举接口。
mtEnum->Next(…, &mt):通过IEnumMediaTypes查询下一个AM_MEDIA_TYPE。GuidToString(mt->majortype):把AM_MEDIA_TYPE的GUID转换成字符串(方便输出)。
【释放】
CoUninitialize():释放CoInitialize()初始化的COM运行环境。
再附上一张代码中涉及到的接口之间的关系:
可以看出从上到下他们之间顺序的排列如下所示:
ICreateDevEnum-->IEnumMoniker-->IMoniker-->IBaseFilter-->IEnumPins-->IPin-->IEnumMediaTypes-->AM_MEDIA_TYPE
源代码
/**
* 最简单的Directshow信息显示例子
* Simplest DirectShow Info
*
* 雷霄骅 Lei Xiaohua
* leixiaohua1020@126.com
* 中国传媒大学/数字电视技术
* Communication University of China / Digital TV Technology
* http://blog.csdn.net/leixiaohua1020
*
* 本程序是一段获取DirectShow滤镜信息的代码。通过本代码可以获得
* DirectShow滤镜信息。适合初学者学习DirectShow。
*
* This code can be used to get Directshow Filter's information.
* Suitable for the beginner of DirectShow.
*/
#include "stdafx.h"
#include <dshow.h>
#include <atlconv.h>
#define OUTPUT_PIN 1
#define OUTPUT_MEDIATYPE 1
char* GuidToString(const GUID &guid)
{
int buf_len=64;
char *buf =(char *)malloc(buf_len);
_snprintf(
buf,
buf_len,
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1],
guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7]);
//printf("%s\n",buf);
return buf;
}
int _tmain(int argc, _TCHAR* argv[])
{
USES_CONVERSION;
// Init COM
HRESULT hr=NULL;
hr= CoInitialize(NULL);
if (FAILED(hr)){
printf("Error, Can not init COM.");
return -1;
}
printf("===============Directshow Filters ===============\n");
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr)){
return hr;
}
IEnumMoniker *pEnumCat = NULL;
//Category
/************************************************************************
Friendly Name CLSID
-------------------------------------------------------------------------
Audio Capture Sources CLSID_AudioInputDeviceCategory
Audio Compressors CLSID_AudioCompressorCategory
Audio Renderers CLSID_AudioRendererCategory
Device Control Filters CLSID_DeviceControlCategory
DirectShow Filters CLSID_LegacyAmFilterCategory
External Renderers CLSID_TransmitCategory
Midi Renderers CLSID_MidiRendererCategory
Video Capture Sources CLSID_VideoInputDeviceCategory
Video Compressors CLSID_VideoCompressorCategory
WDM Stream Decompression Devices CLSID_DVDHWDecodersCategory
WDM Streaming Capture Devices AM_KSCATEGORY_CAPTURE
WDM Streaming Crossbar Devices AM_KSCATEGORY_CROSSBAR
WDM Streaming Rendering Devices AM_KSCATEGORY_RENDER
WDM Streaming Tee/Splitter Devices AM_KSCATEGORY_SPLITTER
WDM Streaming TV Audio Devices AM_KSCATEGORY_TVAUDIO
WDM Streaming TV Tuner Devices AM_KSCATEGORY_TVTUNER
WDM Streaming VBI Codecs AM_KSCATEGORY_VBICODEC
************************************************************************/
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioCompressorCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_MediaMultiplexerCategory, &pEnumCat, 0);
//hr = pSysDevEnum->CreateClassEnumerator(CLSID_LegacyAmFilterCategory, &pEnumCat, 0);
if (hr != S_OK) {
pSysDevEnum->Release();
return -1;
}
IMoniker *pMoniker = NULL;
ULONG monikerFetched;
//Filter
while(pEnumCat->Next(1, &pMoniker, &monikerFetched) == S_OK){
IPropertyBag *pPropBag;
VARIANT varName;
IBaseFilter *pFilter;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,(void **)&pPropBag);
if (FAILED(hr)){
pMoniker->Release();
continue;
}
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
//"FriendlyName": The name of the device.
//"Description": A description of the device.
//Filter Info================
printf("[%s]\n",W2A(varName.bstrVal));
VariantClear(&varName);
//========================
#if OUTPUT_PIN
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,(void**)&pFilter);
if (!pFilter){
continue;
}
IEnumPins * pinEnum = NULL;
IPin * pin = NULL;
ULONG pinFetched = 0;
if (FAILED(pFilter->EnumPins(&pinEnum))){
pinEnum->Release();
continue;
}
pinEnum->Reset();
//Pin Info
while (SUCCEEDED(pinEnum->Next(1, &pin, &pinFetched)) && pinFetched){
if (!pin){
continue;
}
PIN_INFO pinInfo;
if (FAILED(pin->QueryPinInfo(&pinInfo))){
continue;
}
printf("\t[Pin] ");
switch(pinInfo.dir){
case PINDIR_INPUT:printf("Dir:Input \t");break;
case PINDIR_OUTPUT:printf("Dir:Output \t");break;
default:printf("Dir:Unknown\n");break;
}
printf("Name:%s\n",W2A(pinInfo.achName));
//MediaType
#if OUTPUT_MEDIATYPE
IEnumMediaTypes *mtEnum=NULL;
AM_MEDIA_TYPE *mt=NULL;
if( FAILED( pin->EnumMediaTypes( &mtEnum )) )
break;
mtEnum->Reset();
ULONG mtFetched = 0;
while (SUCCEEDED(mtEnum->Next(1, &mt, &mtFetched)) && mtFetched){
printf("\t\t[MediaType]\n");
//Video
char *MEDIATYPE_Video_str=GuidToString(MEDIATYPE_Video);
//Audio
char *MEDIATYPE_Audio_str=GuidToString(MEDIATYPE_Audio);
//Stream
char *MEDIATYPE_Stream_str=GuidToString(MEDIATYPE_Stream);
//Majortype
char *majortype_str=GuidToString(mt->majortype);
//Subtype
char *subtype_str=GuidToString(mt->subtype);
printf("\t\t Majortype:");
if(strcmp(majortype_str,MEDIATYPE_Video_str)==0){
printf("Video\n");
}else if(strcmp(majortype_str,MEDIATYPE_Audio_str)==0){
printf("Audio\n");
}else if(strcmp(majortype_str,MEDIATYPE_Stream_str)==0){
printf("Stream\n");
}else{
printf("Other\n");
}
printf("\t\t Subtype GUID:%s",subtype_str);
free(MEDIATYPE_Video_str);
free(MEDIATYPE_Audio_str);
free(MEDIATYPE_Stream_str);
free(subtype_str);
free(majortype_str);
printf("\n");
}
#endif
pin->Release();
}
pinEnum->Release();
pFilter->Release();
#endif
pPropBag->Release();
pMoniker->Release();
}
pEnumCat->Release();
pSysDevEnum->Release();
printf("=================================================\n");
CoUninitialize();
return 0;
}
运行结果
程序运行的结果如下图所示。从图中可以看出,程序打印出了系统中DirectShow的Filter信息。每个Filter的信息中包含了它的Pin的信息。每个Pin中又包含了Pin中的MediaType信息。
可以通过定义在代码最前面宏 控制输出的Filter信息的类型。定义成“0”的话则不会输出该类的信息。如下所示。
#define OUTPUT_PIN 1 #define OUTPUT_MEDIATYPE 1
下载
Simplest DirectShow Example
项目主页
SourceForge:https://sourceforge.net/projects/simplestdirectshowexample/
Github:https://github.com/leixiaohua1020/simplest_directshow_example
开源中国:http://git.oschina.net/leixiaohua1020/simplest_directshow_example
CDSN下载地址:http://download.csdn.net/detail/leixiaohua1020/8348163
本程序包含了DirectShow开发的示例程序。适合DirectShow初学者进行学习。
它包含了以下几个子程序:
simplest_directshow_player: 最简单的基于DirectShow的视频播放器。
simplest_directshow_player_custom: 最简单的基于DirectShow的视频播放器(Custom)。
playerGUI: 最简单的基于DirectShow的播放器-图形界面版。
simplest_directshow_info: 最简单的Directshow信息显示例子。
simplest_directshow_filter: 目前还未完成。
最简单的基于DirectShow的示例:获取Filter信息的更多相关文章
- 最简单的基于DirectShow的示例:视频播放器自定义版
===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...
- 最简单的基于DirectShow的示例:视频播放器图形界面版
===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...
- 最简单的基于DirectShow的示例:视频播放器
===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...
- 转:最简单的基于 DirectShow 的视频播放器
50行代码实现的一个最简单的基于 DirectShow 的视频播放器 本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectSho ...
- 最简单的基于librtmp的示例:发布H.264(H.264通过RTMP发布)
===================================================== 最简单的基于libRTMP的示例系列文章列表: 最简单的基于librtmp的示例:接收(RT ...
- 最简单的基于librtmp的示例:发布(FLV通过RTMP发布)
===================================================== 最简单的基于libRTMP的示例系列文章列表: 最简单的基于librtmp的示例:接收(RT ...
- 最简单的基于librtmp的示例:接收(RTMP保存为FLV)
===================================================== 最简单的基于libRTMP的示例系列文章列表: 最简单的基于librtmp的示例:接收(RT ...
- 50行代码实现的一个最简单的基于 DirectShow 的视频播放器
本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectShow 播放视频所有必备的函数. 直接贴上代码,具体代码的含义都写在注释中 ...
- 一个简单的基于 DirectShow 的播放器 2(对话框类)
上篇文章分析了一个封装DirectShow各种接口的封装类(CDXGraph):一个简单的基于 DirectShow 的播放器 1(封装类) 本文继续上篇文章,分析一下调用这个封装类(CDXGrap ...
随机推荐
- hdu 5137(2014广州—最短路)
题意:给你一个图,求删除一个点后使1->n的距离最大 思路: 枚举删除点,然后求最短路,取这些最短路的最大值 #include <iostream> #include <cst ...
- hdu 5636 搜索 BestCoder Round #74 (div.2)
Shortest Path Accepts: 40 Submissions: 610 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: ...
- Java连接FTP成功,但是上传是失败,报错:Connected time out
Java代码在本机上传文件到FTP服务器的时候成功,但是部署到测试服务器的时候出现,连接FTP成功但是上传失败,并且报Connected time out错误: 测试服务器和FTP服务都在阿里云上:( ...
- 2017-9-19 c语言预备作业
题目一: (1)我对邹欣老师博客内容的看法 针对邹欣老师的第一种看法,也就是文中所谈的春蚕与园丁的例子.我认为在大学之前的阶段,师生关系可以如此比喻,因为在中学阶段教师与学生的关系,更多地是一个知识的 ...
- Linux学习之CentOS(八)----详解文件的搜寻、查找(转)
which (寻找『运行档』) [root@www ~]# which [-a] command 选项或参数: -a :将所有由 PATH 目录中可以找到的命令均列出,而不止第一个被找到的命令名称 分 ...
- java new 关键字到底做了什么?
一.关键字new概述 "new"可以说是Java开发者最常用的关键字,我们使用new创建对象,使用new并通过类加载器来实例化任何我们需要的东西,但你是否深入了解过new在编译的瞬 ...
- Mysql索引介绍及常见索引的区别
关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车.对于没有索引的表,单表查询可能几十万数据就是瓶颈,而通常大型 ...
- C# 虹软SDK视频人脸识别和注册
一,准备工作 1.Afoge视频参数类 using AForge.Video.DirectShow; using System; using System.Collections.Generic; u ...
- 解读Raft(二 选举和日志复制)
Leader election Raft采用心跳机制来触发Leader选举.Leader周期性的发送心跳(如果有正常的RPC的请求情况下可以不发心跳)包保持自己Leader的角色(避免集群中其他节点认 ...
- MAX(字段)加0与不加0的测试
--max(字段名)中的"字段名"的数据类型是字符型的,"字段名"+ 0后,oracle会隐式的转换成数字型 --测试 )); insert into Test ...