(转)DirectShow实践经验杂谈

1.当向Filter Graph中加入同一个Filter的多个实例时,使用Intelligent connect,优先使用最晚加入Filter Graph中的那个Filter实例。

2.使用IGraphConfig接口可以将Filter加入Cache,以在Intelligent connect时,提高该Filter的连接优先级。如果要加入Cache的Filter已在Graph中,确信它的所有Pin处于断开状态,而且调用IGraphConfig::AddFilterToCache之后,Graph中的Filter实例会自动Remove掉;当Intelligent connect之后,使用了Cache中的某个Filter实例,则这个Filter实例会被自动加入到Graph,而Cache中这个Filter实例也会被Remove掉。

3.在调试Filter时,每次进入CheckMediaType的Media type,我们在VC中只能看到一串UUID数字,很麻烦!下面的代码能将Media type的描述信息Dump到VC的Output window:
void DisplayMediaType(TCHAR *pDescription,const CMediaType *pmt)
{
// Dump the GUID types and a short description
DbgLog((LOG_TRACE,0,TEXT("")));
DbgLog((LOG_TRACE,0,TEXT("%s"),pDescription));
DbgLog((LOG_TRACE,0,TEXT("")));
DbgLog((LOG_TRACE,0,TEXT("Media Type Description")));
DbgLog((LOG_TRACE,0,TEXT("Major type: %s"),GuidNames[*pmt->Type()]));
DbgLog((LOG_TRACE,0,TEXT("Subtype: %s"),GuidNames[*pmt->Subtype()]));
DbgLog((LOG_TRACE,0,TEXT("Subtype description: %s"),GetSubtypeName(pmt->Subtype())));
DbgLog((LOG_TRACE,0,TEXT("Format size: %d"),pmt->cbFormat));
// Dump the generic media types
DbgLog((LOG_TRACE,0,TEXT("Fixed size sample %d"),pmt->IsFixedSize()));
DbgLog((LOG_TRACE,0,TEXT("Temporal compression %d"),pmt->IsTemporalCompressed()));
DbgLog((LOG_TRACE,0,TEXT("Sample size %d"),pmt->GetSampleSize()));
}

4.调试Filter时,想要知道程序是否进入某个函数,可以使用如下的宏定义:
#define DbgFunc(a) DbgLog(( LOG_TRACE /
, 0 /
, TEXT("CFltTracer(Instance %d)::%s") /
, mThisInstance /
, TEXT(a) /
));
使用方法为:
CFltTracer::~CFltTracer()
{
// Other cleaning work...
DbgFunc("~CFltTracer");
}

5.如下的代码,可以将DirectShow的错误码以文本的方式显示出来:
void ShowError(HRESULT hr)
{
if (FAILED(hr))
{
TCHAR szErr[MAX_ERROR_TEXT_LEN];
DWORD res = AMGetErrorText(hr, szErr, MAX_ERROR_TEXT_LEN);
if (res == 0)
{
wsprintf(szErr, "Unknown Error: 0x%2x", hr);
}
MessageBox(0, szErr, TEXT("Error!"), MB_OK | MB_ICONERROR);
}
}

6.0进行DV camcorder编程时要注意,当Filter Graph在运行,而将Camcorder置于Paused状态,"Microsoft DV Camera and VCR"仍然会不停地将Paused时刻的那一帧不断地发送出来(因为DirectShow主要是为Playback设计的,所以这一点对于压缩、合成、写文件的应用非常头疼),送出的Sample时间戳线性递增;而将Camcorder置于Stopped状态,"Microsoft DV Camera and VCR"也就不再送出数据。而Filter Graph上的Pause、Stop操作并不会影响到Camcorder本身的状态。

6.1 Camcorder机器Paused状态持续大约三分钟(测试机为JVC)后,机器的Preview画面会变成蓝屏。此时,即使Filter Graph在运行状态,"Microsoft DV Camera and VCR"也停止输出数据。

7.DirectShow加入Device Filter一般都要靠枚举。Device的名字一般是在枚举的时候,通过IPropertyBag::Read(L"FriendlyName", &varName, 0)获得。对于DV camcorder,这种方式得到的名字为"Microsoft DV Camera and VCR";而另一种方法(必须在Windows Me或XP下),通过读取"Description"属性,可以更详细地得到Camcorder的生产厂商名字。参考代码如下:
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"Description", &varName, 0);
if (FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
}

8.Playback快进(慢进)的支持,可以通过IMediaSeeking::SetRate(或IMediaPosition::put_Rate)来实现。参数为1.0表示正常速度,2.0为双倍速度,0.5为半速;理论上参数为负数时能够实现倒放,但绝大部分Filter不支持倒放。对于Rate改变的响应,主要工作在负责打时间戳的Filter上,有可能是Parser Filter(如AVI Splitter),也有可能是Push模式下的Source Filter;这些Filter需要根据新的Rate重新打好时间戳。一般Decoder Filter不用对Rate改变做出响应,它们收到NewSegment后只要往下传递就行了,但对于一些可能需要改变时间戳的Decoder,则也需要考虑这个Rate的改变。Video Renderer一般也不需要关心Rate的改变,因为进来的Sample已经是按照新的Rate打好时间戳了;Audio Renderer需要对Rate进行更新,因为一般Audio Decoder不会因为Rate的改变而作相应的转换。还有一点,SetRate的调用之前,Filter Graph Manager会先将Filter Graph停止;调用之后,新的Sample时间戳从0开始。Playback Rate的改变会导致Audio很难听,所以此时最好将Audio静音处理。

9.Playback的单帧控制,可以通过Filter Graph Manager上获得的IVideoFrameStep接口来实现。Filter Graph Manager也主要是协同Video Renderer或者Overlay Mixer来实现单帧播放的。IVideoFrameStep接口方法不仅支持单帧跳进,也支持多帧的跳进。在使用接口方法时,最好先调用IVideoFrameStep::CanStep判断是否支持你指定的跳帧操作。调用IVideoFrameStep::Step实现跳进,其中第二个参数为实际实现跳帧功能的Filter,为NULL时Filter Graph Manager默认使用Video Renderer。当Step函数调用成功,Filter Graph Manager会向应用程序发送一个EC_STEP_COMPLETE事件,Filter Graph也自动转入Paused状态。

10.Mpeg1文件的播放可以直接使用微软的MPEG-1 Stream Splitter、MPEG Video Decoder和MPEG Audio Decoder。Video Decoder可以通过IMpegVideoDecoder接口(在mpgcodec.h中定义)进行参数修改,比如可以通过set_GreyScaleOutput设置输出图像是彩色的还是黑白的等;Audio Decoder可以通过IMpegAudioDecoder接口(在mpegtype.h中定义)进行参数设置,比如可以控制解码输出mono或是stereo,左右声道切换(注意:在解码输出mono的时候,不支持动态切换左右声道)等。

 

11.AVI Splitter, Mpeg1 Stream splitter, Mpeg2 splitter只能工作在Pull模式;Mpeg2 Demultiplexer在非Window XP下工作在Push模式,而在Window XP下也能工作在Pull模式。所以,网络客户端接收压缩数据要进行解码时,一般将接收器Source Filter写成Pull模式(因为现成的Parser Filter大都只能工作在Pull模式)。如果要将接收器写成Push模式,则这个Source Filter送出来的数据应该是已经做过Parse处理的(即Video和Audio已分离)。

12.ACM(Audio Compression Manager)和VCM(Video Compression Manager)在DirectShow中都是通过包装Filter应用的。ACM Wrapper Filter,作为解压用时(主要进行Audio格式的转换,输出PCM数据),注册在"DirectShow Filters"目录下,Merit值为MERIT_NORMAL;作为压缩用时,各个Audio压缩器注册在"Audio Compressors"目录(CLSID_AudioCompressorCategory)下,Merit值为MERIT_DO_NOT_USE。注意:这里的Audio Compressor不能通过CoCreateInstance创建,而只能通过系统枚举。VCM包装Filter作为解压用时,即为AVI Decompressor Filter,一般实现Video从YUV到RGB格式的转换(注意:MPEG数据的压缩/解码都不是通过VCM包装Filter实现的);作为压缩用时,各压缩器注册在"Video Compressors"目录(CLSID_VideoCompressorCategory)下,Merit值为MERIT_DO_NOT_USE。注意:这里的Video Compressor也不能直接通过CoCreateInstance创建。

13.微软提供了两个Tee Filter:Smart Tee和Infinite Pin Tee Filter。前者有两个Output pin,且Preview pin输出的Sample已经去掉时间戳;后者,可以动态产生无数个Output pin,而且各个Output pin输出的Sample是完全一样的。

14.在Filtr Graph运行状态下,可以动态加入新的Filter,但不能删掉Filter,也不能断开Filter之间的Pin连接。Filter从Filter Graph中删除必须在Stopped状态,删除前将这个Filter的Pin断开不是必要的!(连接着的Pin可以通过IFilterGraph:Disconnect断开,并且连接两头的Pin都要调用一次!)

15.AVI Mux问题。四种工作模式(通过Filter上的IConfigInterleaving::put_Mode设置):INTERLEAVE_NONE,对输入的数据不缓存,各帧数据按照它们到达Mux的顺序直接写入文件中,速度最快;INTERLEAVE_FULL,对Video和Audio的交叉打包精确控制,每次合成都要阻塞等待等量的Video、Audio数据,适合文件源的视频编辑等应用;INTERLEAVE_CAPTURE,处于前两种模式之间,尽量不使用数据缓存,在一个Pin上数据到达后等待另一个Pin数据到达时,可能会丢帧,适合Live Source Capture应用,注意此时Audio的Capture buffer应该小于0.5秒;INTERLEAVE_NONE_BUFFERED,仅在Win XP下用,类似于INTERLEAVE_NONE,只是这种模式生成的文件较小。还有另外一个接口方法IConfigInterleaving::put_Interleaving,设置打包频率和Audio的预留(Preroll),推荐打包频率为1秒钟一次,Audio预留750ms。

16.AVI 1.0文件大小有上限1GB,AVI 2.0文件没有这个限制。AVI Mux默认总是生成2.0的文件(1.0的文件主要是老的VFW生成的),也可以通过AVI Mux上的IConfigAviMux::SetOutputCompatibilityIndex来设置生成1.0的文件,以保持向后兼容。另一个接口方法IConfigAviMux::SetMasterStream,用以同步多个输入流,特别是在不同源的video、Audio Capture时,两个源的Capture rate可能有细微的差别。设置了Master stream之后,Mux会修改AVI文件的Playback rates(AVIStreamHeader结构的dwScale和dwRate两个成员变量)。推荐将Audio stream设为Master。

17.在同一个Filter Graph中,既有Live Source(比如Camcorder,capture devices,mpeg2 demux等,他们自带Reference Clock),又有Default DirectSound Device(声卡带有时钟),默认情况下,Filter Graph Manager选择Live Source的参考时钟。有时候会出现Live Source数据流传输了几十个Sample后会不在传送Sample出来。可能的原因是,有多个参考时钟时回放速率匹配问题。解决的方法是,选择声卡的时钟,或者设置整个Filter Graph不使用时钟。

18.0目前(DirectX8.1),微软并没有提供.dv文件的“拉”Filter。如果要使用DV文件,一个变通的方法是,将DV数据保存到AVI文件中。播放这种文件,AVI Splitter会识别出DV数据,并送DV Splitter(微软提供,Push模式)和DV Video Decoder(微软提供)进行解码。

18.1在回放含有DV的AVI文件时,我们发现,真正实现IMediaSeeking的是AVI Splitter,而不是DV Splitter(微软提供)。DV Splitter的Audio output pin或者Video Output pin均将IMediaSeeking的请求通过其Input pin传递到Up stream去了。

18.2如果自己写一个"DV Parser Filter",需要注意的是,从Filter Source中拉数据,每次拉的数据大小一般是按512字节对齐的,所以不会是每次拉一个DV帧(PAL为144000字节,NTSC为120000字节)。而微软的DV Splitter输入的Sample要求是一帧一帧的数据(注意:如果每次送的数据太多了,会导致无法正常解码;如果送少了,导致后续Filter没有足够的数据进行解码,会发生Filter Graph的状态转换出错,即可能无法转入Paused状态),所以我们必须在DV Parser上对拉出的数据进行必要的缓存。而且,在处理Seek时,新的Seeking位置也要考虑“字节对齐”的问题。
其实,为DV文件写一个Source Filter,直接将DV数据从文件中读出后push出去,问题就要简单一点!

19.Tee Filter问题。微软提供的Smart Tee(没有源码)与Infinite Pin Tee Filter(有源码)相比,后者的性能要好一点。两者的区别是,前者将Preview pin出来的Sample进行了“去时间戳”处理,而后者只是简单地将一个Sample分别在各个output pin上输出。

20.写多进一出,或者是一进多出的Filter,基类可以选择CTransformFilter或者CTransInPlaceFilter,虽然它们在BaseClasses中的实现都是一进一出的。一般的做法为,保持原有的Input pin和Output pin为“主流”的链路,以这个标准Input pin的数据“流入”,来驱动协调其他Pin数据处理后,再输入。需要注意的是,必须重载基类Filter的GetPinCount、GetPin实现,以增加新的Pin;重载FindPin支持新加pin;重载Filter的Pause或Stop实现,因为可能还要同步新增加的pin的数据流(如果新增加的pin在Filter要转入Paused状态时还处于死循环或阻塞,则可能导致Filter状态转换失败,出现Frozen现象);新增加Input pin一般从CBaseInputPin上继承,Output pin从CBaseOutputPin上继承,而且一般都要重载以下几个函数的实现:CheckMediaType、Receive、EndOfStream、BeginFlush、EndFlush。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DirectShow是一种用于多媒体应用程序开发的编程框架,它是由微软开发的。DirectShow Demo是一个演示性的示例程序,用于展示和演示DirectShow框架的功能和用法。 DirectShow Demo可以通过各种实例演示和展示DirectShow框架的各种特性和功能。它可以通过创建各种类型的多媒体图形,如音频和视频的捕捉、换、播放和渲染等,来向开发者展示如何使用DirectShow来构建多媒体应用程序。 通过DirectShow Demo,开发者可以学习如何使用DirectShow编写音频和视频播放器、录像机、视频编辑器等应用程序。它提供了丰富的演示示例,包括如何使用DirectShow进行实时音频和视频的捕捉,如何应用各种音频和视频滤波器来处理和换多媒体数据,以及如何使用DirectShow进行多媒体渲染和播放等。 通过DirectShow Demo,开发者可以深入了解DirectShow框架的核心概念和基本原理,掌握多媒体应用程序的开发技巧和方法。它对于那些希望学习和探索DirectShow框架的开发者来说是非常有用的。 总之,DirectShow Demo是一个用于演示和展示DirectShow框架功能和用法的示例程序,通过它,开发者可以学习和掌握使用DirectShow构建多媒体应用程序的技术和方法。 ### 回答2: DirectShow是一个由Microsoft开发的多媒体框架,它提供了一套丰富的API和工具,用于处理音频和视频数据。DirectShow Demo是指使用DirectShow框架编写的演示程序,用来展示DirectShow的功能和用法。 DirectShow Demo通常包含一系列示例代码,用于演示DirectShow的各种功能,比如播放音频和视频、捕获音频和视频、处理音频和视频等。这些示例代码展示了如何使用DirectShow接口来实现各种多媒体处理操作。 通过DirectShow Demo,开发者可以学习和理解DirectShow框架的使用方法,并参考示例代码来实现自己的多媒体应用程序。开发者可以通过DirectShow Demo了解如何创建和管理DirectShow滤波器、建立滤波器图形、设置音视频格式等。 使用DirectShow Demo,开发者可以实现各种多媒体处理功能,比如播放各种格式的音乐和视频文件、从摄像头捕获视频、从麦克风捕获音频、对音频进行特效处理等。开发者可以根据自己的需求,参考DirectShow Demo中的示例代码,快速实现自己的多媒体应用程序。 总之,DirectShow Demo是一个用于展示DirectShow功能和用法的示例程序集合,通过学习和参考其中的示例代码,开发者可以快速掌握DirectShow框架,并实现各种多媒体处理功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值