我使用Delphi 6 Pro与DSPACK DirectShow组件库创建一个DirectShow过滤器,从自定义音频源提供Wav格式的数据。只是为了非常清楚,我提供原始的PCM音频样本作为字节数据。没有涉及到Wave文件,但我的过滤器图中的其他过滤器下游期望输出引脚以字节形式提供标准WAV格式的示例数据。
注意:当我从自定义音频源获得数据时,我将其格式化为所需的通道数,采样率和每个采样位,并将其存储在我创建的TWaveFile对象中。该对象有一个正确格式化的TWaveFormatEx数据成员,该成员被正确设置以反映我存储的数据的底层格式。
我不知道如何在GetMediaType()调用期间正确设置MediaType参数:
function TBCPushPinPlayAudio.GetMediaType(MediaType: PAMMediaType): HResult;
.......
with FWaveFile.WaveFormatEx do
begin
MediaType.majortype := (1)
MediaType.subtype := (2)
MediaType.formattype := (3)
MediaType.bTemporalCompression := False;
MediaType.bFixedSizeSamples := True;
MediaType.pbFormat := (4)
// Number of bytes per sample is the number of channels in the
// Wave audio data times the number of bytes per sample
// (wBitsPerSample div 8);
MediaType.lSampleSize := nChannels * (wBitsPerSample div 8);
end;
(1)、(2)和(3)的正确值是什么?我知道MEDIATYPE_Audio, MEDIATYPE_Stream和MEDIASUBTYPE_WAVE GUID常量,但我不确定去哪里。
此外,我假设我需要将WaveFormatEx结构/记录从我的FWaveFile对象复制到pbFormat指针(4)。我对此有两个问题:
1)我假设应该使用CoTaskMemAlloc()来创建一个新的TWaveFormatEx对象,并复制我的FWaveFile对象的TWaveFormatEx对象到它,之前分配pbFormat指针给它,正确的?
2) TWaveFormatEx是传递的正确结构吗?下面是TWaveFormatEx的定义:
tWAVEFORMATEX = packed record
wFormatTag: Word; { format type }
nChannels: Word; { number of channels (i.e. mono, stereo, etc.) }
nSamplesPerSec: DWORD; { sample rate }
nAvgBytesPerSec: DWORD; { for buffer estimation }
nBlockAlign: Word; { block size of data }
wBitsPerSample: Word; { number of bits per sample of mono data }
cbSize: Word; { the count in bytes of the size of }
结束;
更新:11-12-2011
我想强调@Roman R在他接受的回复中附加的评论之一,他告诉我使用MEDIASUBTYPE_PCM作为子类型,因为它是如此重要。我浪费了大量的时间来追踪DirectShow"没有中间过滤器组合"错误,因为我忘记为子类型使用该值,而使用(错误地)MEDIASUBTYPE_WAVE。MEDIASUBTYPE_WAVE与许多其他过滤器(如系统捕获过滤器)不兼容,这是失败的根本原因。这里更重要的教训是,如果您正在调试过滤器间媒体格式协商错误,请确保所连接的引脚之间的格式完全相等。我在最初的调试过程中犯了一个错误,只比较了WAV格式参数(格式标签,通道数量,每个样本的位数,采样率),这些参数在引脚之间是相同的。但是,由于我使用MEDIASUBTYPE_WAVE不当,导致子类型的差异导致引脚连接失败。当我按照Roman的建议将子类型更改为MEDIASUBTYPE_PCM时,问题就消失了。
(1)为MEDIATYPE_Audio
。
(2)是典型的从FOURCC代码到GUID的映射,参见媒体类型,音频媒体类型部分。
(3)为FORMAT_WaveFormatEx
。
(4)是指向WAVEFORMATEX
结构的指针(通常由COM任务内存分配器API分配)。
1) -是的,你应该分配内存,把有效的数据在那里,通过复制或直接初始化,并把这个指针到pbFormat
和结构大小到cbFormat
。
2) -是的,它看起来不错,它是这样定义的:WAVEFORMATEX结构。