第一篇:directshow教程
Directshow教程0.1
MSDN翻译系列
:dinjee
说明:如果有任何问题请联系din-je@163.com。是本人业余翻译的如果有错误请直接发到我邮箱我会立刻改正,directshow的其他文章我会在以后不断翻译出来。如果觉得好请帮我作作宣传。欢迎转载,但是禁止修改。
Directshow起步。
本章主要介绍diirectshow在编写程序时所需的基本概念。在本章你可以总揽下directshow技术。你必须在总体上对本章的编程和媒体有所了解。
本章将介绍
。设置编译环境
。介绍directshow应用程序编程
。如何播放一个文件
设置编译环境:
你可以编译工程在命令行模式下或者在vs集成环境中
头文件
所有的directshow应用程序都使用下面的头文件。
Dshow。H
部分directshow接口需要附加的头文件。这些文件会在接口的注意中给出。所需的库文件
directshow需要如下的库文件
strmiidl。Lib 该库包含CLSIDs和IIDs的接口。所有的directshow都需要该库。Quartz。Lib 该库包含AMGetErrorText函数。如果你没有调用该函数,该库没有用。记住在你的编译环境中必须把directx SDK 的头文件库和连接库的目录作为vs优先搜索的路径。这样可以保证编译的时候用的是最新版本的文件。
介绍directshow应用程序编程
本章介绍编写一个directshow程序的基本技术和概念,读完本章你就可以写个你自己的directshow的应用程序了。
滤镜和图像滤镜
directshow是由被称作滤镜的东西构成的。滤镜是一个软件包用来执行对多媒体流的一些操作。比如directshow的滤镜可以
读出一个文件
从视频捕捉设备获取视频流
解码各种各样的多媒体格式,比如MPEG-1S视频。
传输视频和音频到屏幕和声卡。
滤镜几乎完成视频播放所需要的从输入到输出的所有功能。比如一个MPEG-1的滤镜。它可以输入MPEG码流然后输出图像帧用于后续显示
在directshow程序中只要执行把滤镜连接在一起就可以了。就是把一个滤镜的输入和另外一个滤镜的输出连接在一起就可以了。一组连接在一起的滤镜叫做图像滤镜。比如下面的图示
就是一个播放AVI文件的图像滤镜的例子
正如上面图示的,文件滤镜把AVI文件从硬盘读入。AVI分离滤镜分离文件流为两个数据流。一个是视频压缩流,一个是硬盘流。AVI解压滤镜用于解压视频流生成视频帧。视频显示滤镜用于把视频帧用directdraw或者GDI显示到屏幕上。音频留输入到默认声音设备滤镜把声音通过directsound播放出来。
因此应用程序就不用管理任何数据流。代替的,滤镜被叫做高端组件叫做图像滤镜的进行控制。程序只要创建一些高级API。就像RUN(用于在图像控件中移动数据)或者STOP(用于停止数据流)。但是如果你要求更多的数据流控制,那你也可以直接存取控制的COM接口。图像滤镜也会反馈一定的事件消息给应用程序。
图像滤镜可以服务另外的目的。提供给应用程序创建图像滤镜的方法,还有把各个滤镜连接在一起的方法。(directshow同时也提供一些帮助的组件可以简单的处理。这些全部都有在文档中描述。
编写一个directshow程序
总的来说,写个directshow程序必须进行这三个步骤。就像下面的图例。
1. 创建个图像滤镜管理的实例
2. 然后用图像理解管理实例建立一个图像滤镜。外部滤镜间依赖于这个图像滤镜。
3. 应用程序应用图像滤镜控制图像滤镜和数字流在滤镜中的流动。通过这些处理。应用程
序也应该回应滤镜管理事件。
当处理结束后。应用程序释放图像滤镜管理器和所有的滤镜。因为directshow是基于COM的,因此图像滤镜管理和滤镜都是COM对象。因此你必须对COM客户端编程有所了解。具体的可以在DirectX SDK中的一篇文章叫做《Using COM》中有很好的介绍COM对象的资料。而且是有很多COM编程的书籍可以参考。
如何播放一个文件
本文章是想让你喜欢上Directshwo编程。我们要创建一个简单的命令行下的程序用于播放音频或者视频文件,这个程序实在是太简单了,可是它所完成的功能却是非常强大。这个程序只要短短的几行的代码就可以搞定了。可是它所完成的功能却是以前只有专门公司才能开发出来的软件所能实现的。它可以用来演示播放任何的多媒体文件。用它你可以立刻喜欢上directshow的编程。
就像上面的文章说描述的那样,一个directshow应用程序总是有三个基本的步骤。
1.建立个图像滤镜管理器的实例
2.用图像滤镜管理建立一个图像滤镜
3.给它运行的消息,让数据流在各个滤镜中移动。
好了,我们开始编写我们直接的多媒体演示程序。
首先我们必须调用CoInitialize来初始化COM库。
(记住directshow在编程的时候全部都没有传统编写COM的影子,因此初学者很容易被它的假象所欺骗,以为directshow根本就不是COM的,或者认为COM就是那么简单。其实directshow就有点象MFC,通过c 的封装技术和其他大量的技术把COM技术的很多细节都隐藏其来。其实在背后微软已经为我们写了很多很多的代码。我们应该感谢微软为我们作的一切,但是我们也应该佩服微软。居然可以把代码的复用技术发挥到如此的境界。这些是我们国内软件企业所要学习的地方。废话了)HRESULT hr = CoInitialize(NULL);
if(FAILED(hr))
{
// Add error-handling code here.(Omitted for clarity.)
}
为了保持程序的简单,这个例子忽略了返回值。但是你必须在你自己编写的代码中始终检查从任何方法中返回的HERSULT值。这个是很重要的因为他可能是空值。那在后续的调用的时候将产生很多莫名其妙的错误。问题严重哦。
接下来,我们调用CoCreateInstance用来建立滤镜管理器
IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER, IID_IGraphBuilder,(void **)&pGraph);
如上所示,传入的第一个参数类的标识是CLSID_FilterGraph。按照字面的意思就是用于创建图像滤镜。返回我们就得到了一个HERSULT了,这个是指向滤镜的一个句柄。这个东西就是一个图像滤镜了,它将来要用到所有其他的后续处理之中。还有那个执行描述参数传入的是CLSCTX_INPROC_SERVER。Directshow支持释放线程模型。所以你可以调用CoinitializeEx函数用COINIT_MULTITHREADED参数。
该函数还返回了个IgraphBuilder接口。该接口包含了大多数的用于构建图像滤镜的方法。还用两个方法被用于这个例子。
。ImediaControl接口,该接口用于控制数据流。可以用来停止和启动数据流。
。ImediaEvent接口,该接口用于获取图像滤镜的的事件。在这个例子中我们用来等待播放结束。
这两个滤镜都是从图像滤镜引出来的。我们可以用刚才返回的IgraphBuilder来得到他们。下面是范例。IMediaControl *pControl;
IMediaEvent*pEvent;hr = pGraph->QueryInterface(IID_IMediaControl,(void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent,(void **)&pEvent);
接下来你就可以建立个图像滤镜。用来播放文件。可是这也是很简单的调用
hr = pGraph->RenderFile(L“C:Example.avi”, NULL);
IgrapBuilder::RenderFile方法可以用来播放特定的文件。第一次参数就是文件名,不过必须是UNICODE的。第二个参数是用来保留的,现在只要填NULL就可以了。
当然了,如果输入的文件名有错误,或者是根本就不认识的格式,它就会返回错误。这个时候就应该通过一些错误的代码来报告错误。因为这个例子只是简单的例子,因此没有这些代码,我们始终假设文件是存在的,并且格式是可以被解码的。要是代用成功图像滤镜就会准备播放了。现在我们可以调用ImediaControl::Run函数让他运行。
hr = pControl->Run();
一旦调用成功,数据就开始在滤镜中移动。并且将其播放出来。播放是在另外的线程后台进行的。我们只要等待它播放结束就可以了。我们可以调用ImediaEvent::WaitForCompletion还等待播放结束。
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
该方法会一直等待知道播放解说或者播放出错返回。那个参数INFINITE是告诉该函数,我要等待直到播放结束才返回。不过还有其他的参数,可以方便的使用可以参考Responding to Events这篇文章。
当应用程序结束就可以释放这些接口的指针用于关闭.COM库 pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
下面是完整的代码,真的很少。#include
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent*pEvent = NULL;
// Initialize the COM library.HRESULT hr = CoInitialize(NULL);
if(FAILED(hr))
{
printf(“ERRORCould not create the Filter Graph Manager.”);
return;
}
hr = pGraph->QueryInterface(IID_IMediaControl,(void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent,(void **)&pEvent);
// Build the graph.IMPORTANT: Change this string to a file on your system.hr = pGraph->RenderFile(L“C:Example.avi”, NULL);
if(SUCCEEDED(hr))
{
// Run the graph.hr = pControl->Run();
if(SUCCEEDED(hr))
{
// Wait for completion.long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
说明:如果有任何问题请联系din-je@163.com。是本人业余翻译的如果有错误请直接发到我邮箱我会立刻改正,directshow的其他文章我会在以后不断翻译出来。如果觉得好请帮我作作宣传。欢迎转载,但是禁止修改。
第二篇:directshow是什么
directshow是什么DirectShow是微软公司提供的一套在Windows平台上进行流媒体处理的开发包,与
D i r e c t X 开发包一起发布。DirectShow为多媒体流的捕捉和回放提供了强有力的支持。运用DirectShow可以很方便地从支持 W D M 驱动模型的采集卡上捕获数据,并且进行相应的后期处理乃至存储到文件中。它广泛地支持各种媒体格式,包括 Asf、Mpeg、Avi、Dv、Mp3、Wave 等等,使得多媒体数据的回放变得轻而易举。另外,DirectShow 还集成了DirectX 其它部分(比如DirectDraw、DirectSound)的技术,直接支持 DVD的播放,视频的非线性编辑,以及与数字摄像机的数据交换。更值得一提的是,DirectShow提供的是一种开放式的开发环境,我们可以根据自己的需要定制自己的组件。利用 DirectShow 支持多线程的特点,用一个线程实现数据的采集与回放,另一个线程进行图像处理,从而达到视频监控的目的。DirectShow是基于模块化,每个功能模块都采取COM 组件方式,称为Filter,在DirectShow中只要拥有相应的分析和解码Filter 就可以支持任何多媒体的格式。
DirectShow提供了一系列的标准的模块可用于应用开发,开发者也可以开发自己的功能Filter 来扩展DirectShow 的应用。DirectShow的体系结构中主要有三大类功能:多媒体数据的采集功能、格式转换传输功能以及显示存储功能,这三大功能DirectShow 分别提供了Filter:SourceFilters、Transform Filters和RenderingFilters 来支持。Source Filters主要负责取得媒体数据,数据源可以是文件、计算机里的采集卡、数字摄像机等,然后将数据往下传输;TransformFitlers主要负责数据的格式转换和传输(如编码与解码);Rendering Filtes主要负责数据的最终展现,可以将数据送给声卡、显卡进行多媒体的演示,也可以输出到文件进行存储。DirectShow提供了大量基础的Filter,同时DirectShow还允许用户可以根据一定的接口和数据规则来定制符合自己实际应用需求的Filter。各个Filter在Filter Graph中按一定的顺序连接成一条“流水线”进行协同工作。
第三篇:DirectShow配置
vs2022下directshow的配置(2022-09-14 16:56:09)
转载
标签:分类: 沧海拾贝
directx
directshow
vs2022
配置
近来由于要做一个流媒体播放器,调研后决定在directshow的框架下做。在比较老的资料里可以知道:directshow是包含在directx SDK里面的。这里要强调一点,这是在DirectX 9.0b之前的情况,在9.0c以后,directshow和DirectX就彻底分家了,directshow被移到了windows platform sdk里。如果你只安装了DirectX9.0b之后的版本,是没有directshow的。
我的安装目录是C:Program FilesMicrosoft DirectX SDK(December 2022)。安装好了后,找到C:Program FilesMicrosoft DirectX SDK(December 2022)SamplesC DirectShowBaseClasses下的baseclasses.sln,打开后可能会提示转换,注意留下备份。编译通过后会生成strmbasd.lib,在debug或者release目录下(取决于你程序生成的版本),第一步工作就结束了。如果编译的时候出现错误,一般是一些变量定义方面的错误,VS2k8不支持默认int定义,也就是说你如果不指定一个数据的类型,编译器会生成一个错误。而directshow里的sample代码很多都是基于VC6版本的老代码。总之根据编译器的提示把变量类型声明添上就行了,不难。
第一步工作完成后,就可以开始用directshow了。下面是使用前的准备工作。
1.首先,点击工具->选项->项目和解决方案->VC 目录。如图添加两个引用: C:Program FilesMicrosoft DirectX SDK(December
2022)SamplesC DirectShowBaseClasses
C:Program FilesMicrosoft DirectX SDK(December 2022)Include 注意:请将C:Program FilesMicrosoft DirectX SDK(December 2022)替换为你安装directX所在的目录。
2.如图,再添加库文件的引用。
C:Program FilesMicrosoft DirectX SDK(December
2022SamplesC DirectShowBaseClassesDebug
C:Program FilesMicrosoft DirectX SDK(December 2022)Lib
3.新建一基于对话框的MFC程序DirectShowEx,建成后点项目->属性->连接器->命令行,在附加选项中输入strmbasd.lib
4.在directShowEx.h中添加
#include
#include
将对话框初始化函数OnInitDialog()中的内容替代如下:
CDialog::OnInitDialog();
// Add “About...” menu item to system menu.// IDM_ABOUTBOX must be in the system command range.ASSERT((IDM_ABOUTBOX & 0xFFF0)== IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if(pSysMenu!= NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog.The framework does this automatically//when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE);// Set big icon
SetIcon(m_hIcon, FALSE);// Set small icon
// TODO: Add extra initialization here
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
HRESULT hr = CoInitialize(NULL);
if(FAILED(hr))
{
printf(“can't coinitizlize”);
return-1;
};
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&pGraph);
if(FAILED(hr))
{
printf(“can't create filtergraph”);
return-1;
}
hr = pGraph->QueryInterface(IID_IMediaControl,(void**)&pControl);hr = pGraph->QueryInterface(IID_IMediaEvent,(void**)&pEvent);
hr = pGraph->RenderFile(L“F://lx.avi”, NULL);
if(FAILED(hr))
{
printf(“cant't renderfile”);
return-1;
}
hr = pControl->Run();
if(FAILED(hr))
{
printf(“can't run”);
return-1;
}
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
pControl->Release();
pEvent->Release();
pControl->Release();
CoUninitialize();
printf(“Hello World!n”);
return 0;
return TRUE;// return TRUEunless you set the focus to a control
Ctrl F5编译运行,一切OK。
第四篇:DirectShow常见问题
一、配置方法
1、先编译SamplesC DirectShowBaseClasses中的工程文件。注意工程的默认选项是D ebug_Unicode的,在非Unicode的工程中使用还需要编译Debug版本的。
“DXSDK90SAMPLESC DIRECTSHOWBASECLASSESbaseclasses.dsw的release版本”,指的是运行DXSDK90SAMPLESC DIRECTSHOWBASECLASSESbaseclasses.dsw前,先在VC中选择Build->Set Active Configuration,再在对话框中选择BaseClasses-Win32 Release??
2、需要设置好VC中目录的设置
include的目录中添加 C:DXSDKSamplesC DirectShowBaseClasses
Lib的目录中添加 C:DXSDKSamplesC DirectShowBaseClassesDebug3、使用DirectShow时应该先执行
CoInitialize(NULL);
初始化COM,结束前
CoUninitialize();
关闭COM4、使用DirectShow的工程需要添加下面两个头文件
#include
#include //CComPtr模板的定义
同时需要调整编译的选项
#pragma comment(lib,“strmbasd.lib”)
#pragma comment(lib,“winmm.lib”)
#pragma comment(linker,“/NODEFAULTLIB:libcmtd.lib”)
注意,VC自带的库中也有strmbasd.lib文件。一定要保证连接到DS的库中,否则会出现 strmbasd.lib(dllsetup.obj): error LNK2022: unresolved external symbol “class CFactoryTemplate * g_Templates”(?g_Templates@@3PAVCFactoryTemplate@@A)
strmbasd.lib(dllentry.obj): error LNK2022: unresolved external symbol “class CFactoryTemplate * g_Templates”(?g_Templates@@3PAVCFactoryTemplate@@A)
strmbasd.lib(dllsetup.obj): error LNK2022: unresolved external symbol “int g_cTemplates”(?g_cTemplates@@3HA)
strmbasd.lib(dllentry.obj): error LNK2022: unresolved external symbol “int g_cTemplates”(?g_cTemplates@@3HA)
之类的错误。
二.编译后出现的错误:
1、syntax error : identifier 'DWORD_PTR'
如果你安装了Miscrosof Platform SDK, 你也许会看到:
Compiling...e:directx9samplesc directshowbaseclasseswxutil.h(53): error C2061: syntax error : identifier 'DWORD_PTR'
e:directx9samplesc directshowbaseclassesctlutil.h(43): error C2504: 'IBasicVideo2' : base class undefined
e:directx9samplesc directshowbaseclassesctlutil.h(904): error C2146: syntax error : missing ';' before identifier 'm_dwAdvise' e:directx9samplesc directshowbaseclassesctlutil.h(90): error C2501: 'DWORD_PTR' : missing storage-class or type specifierse如果发生这种情况,你应该从“Tools”目录中选择“Option”,然后在include directory中将Platform SDK加到
VC inlcude之前:
2、LINK : fatal error LNK1104: cannot open file “mfc42ud.lib” mfc42ud.lib是专门给unicode用的build-->set active Configuration--> XXX win32 debug 这样就可以了
3、“CComPtr< ”怎么用?
CComPtr
error C2143: syntax error : missing ';' before '<'
error C2501: 'CComPtr' : missing storage-class or type specifiers error C2059: syntax error : '<'
error C2238: unexpected token(s)preceding ';'
原因:缺少文件,在vc6中是atlbase.h,可能在.net中是atlcomcli.h 解决方法:在stdafx.h中加入#include
4、'ISampleGrabber' : undeclared identifier
加入代码#include
“C:DXSDKSamplesC DirectShowCommondshowutil.cpp并且需要在project->settings-> link 中object/libary modules 中填加
C:DXSDKSamplesC DirectShowBaseClassesdebugstrmbasd.lib winmm.lib ,同时要保证stdafx.h中 有#include #include
5、调用CoInitializeEx(),编译后显示未定义
CoInitializeEx()是利用COM组件时每个线程都要调用的函数,使用这个函数需要有如下设置:在Project-> setting-> C/C 标签下的Preprocessor definitions中加入”_WIN32_WINNT=0x400"语句
第五篇:DirectShow重要接口
DirectShow重要接口
DirectShow 的重要接口
DirectShow采用了COM标准,所以很多重要的功能都是通过COM接口来完成。下面就列举一些重要的DirectShow的接口。
(1)IGraphBuilder接口
用于构造Filter Graph的接口,建立和管理一系列的Filter,过滤和处理源媒体流。
(2)IMediaControl接口
用于控制多媒体流在过滤器图表中的流动,如流的启动和停止。
(3)IMediaEvent接口
用于捕获播放过程中发生的事件,并通知应用程序,如EC_COMPLETE等。
(4)IVideoWindow接口
用于控制视频窗口的属性。
(5)IMeadiaSeeking接口
用于查找媒体的接口,定位流媒体,控制多媒体数据播放提供精确控制。
(6)IBaseFilter接口
从ImediaFilter接口继承,用来定义一个具体的过滤器指针,并对多媒体数据进行处理。
(7)IPin接口
用于管理两个过滤器之间的Pin,从而连接过滤器。
(8)IsampleGrabberCB接口
是Sample Grabber过滤器的一个接口,用于当流媒体数据通过过滤器时进行采样以获得帧图象。
用DirectShow来使用摄像头,一般要求摄像头的驱动是WDM格式的,当然,一些比较老的驱动格式DirectShow也可支持。在DirectShow中,有一个Sample Grabber过滤器,它是一个可以被插入流的过滤器,它有自己的缓冲,存放采样。我们就可以用它来从一个视频文件中简单的扑获一桢。DirectShow通过图形过滤管理器(Filter Graph Manager)来与上层应
用程序和下层的驱动进行联系。DirectShow通过捕获过滤器(Capture Filter)来支持对摄像头的捕获,一个捕获过滤器有多个插口(pin),其中的预览(preview)插口可用来进行显示祯图象。
1、创建图形过滤管理器Filter Graph
如上面原理所述,首先要创建Filter Graph:
CComPtr< IGraphBuilder > m_pGraph;
hr=m_pGraph.CoCreateInstance(CLSID_FilterGraph);
2、连接设备
还要创建系统枚举器组件对象:
CComPtr<ICreateDevEnum>
pCreateDevEnum;pCreateDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum);
然后使用接口方法CreateClassEnumerator()为指定的Filter注册类型目录创建一个枚举器,并获得IenumMoniker接口:
CComPtr< IEnumMoniker > pEm;
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);
接着在调用BindToObject()以后,可以将设备标识生成一个DirectShow Filter,将其加到Filter Graph中就可以参与工作了。
CComPtr< IMoniker > pM;
CComPtr< IPropertyBag > pBag;
hr=pM->BindToStorage(0,0,ID_IPropertyBag,(void**)&pBag);
3、创建Sample Grabber过滤器
CComPtr< ISampleGrabber > m_pGrabber
hr=m_pGrabber.CoCreateInstance(CLSID_SampleGrabber);
当创建好SampleGrabber以后,在Sample Grabber 过滤器连接到别的过滤器之前你必须配置它。然后查询IsampleGrabber接口,还要设置流媒体类型:
m_pGrabber->SetMediaType();
可以仅仅指定主媒体类型;或者主类型加子类型;或者主类型,子类型和类型格式。然后就把它加载到FilterGraph中去:
m_pGraph->AddFilter(pGrabBase,“Grabber”);
4、查找Filter Graph 的Pin并完成后续连接。
接下来就可以通过调用IGraphBuilder 的FindPin()接口来查找过滤管理器中的Pin接口,并通过ICaptureGraphBuilder2 中的接口RenderStream()来完成后续的连接。
hr=pCGB2->FindPin(pCap,PINDIR_OUTPUT,&PIN_CATEGORY_VIDEOPORT, NULL,FALSE,0,&pVPPin);
hr=pCGB2->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, pCap,pGrabBase,pRenderer);
5、获取流媒体类型并运行
通过GetConnectedMediaType()获取连接流媒体的类型以后,我们可以通过
IsampleGrabberCB类的接口BufferCB()来把视频的数据拷贝到自定义的缓冲区中,然后通过在缓冲区的拷贝进行视频到图象数据的拷贝。最后运行﹕
CComQIPtr<IMediaControl,&IID_IMediaControl > pControl = m_pGraph;hr = pControl->Run();