我使用 Delphi 6 Pro 和 DSPACK DirectShow 组件库来创建一个 DirectShow 过滤器,该过滤器从自定义音频源提供 Wav 格式的数据。需要明确的是,我将原始 PCM 音频样本作为字节数据提供。不涉及 Wave 文件,但 Filter Graph 下游的其他 Filter 期望输出引脚以字节形式提供标准 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 }
end;
更新:2011 年 12 月 11 日
我想强调 @Roman R 附在他接受的回复中的评论之一,他告诉我使用媒体子类型_PCM对于子类型,因为它是如此重要。我为了寻找 DirectShow 而浪费了大量的时间”无中间过滤组合“错误,因为我忘记使用该值作为子类型并且正在使用(错误地)MEDIASUBTYPE_WAVE反而。 MEDIASUBTYPE_WAVE 与许多其他过滤器(例如系统捕获过滤器)不兼容,这是失败的根本原因。这里更大的教训是,如果您正在调试过滤器间媒体格式协商错误,请确保所连接的引脚之间的格式是完全地平等的。我在最初的调试过程中犯了一个错误,即只比较引脚之间相同的 WAV 格式参数(格式标签、通道数、每个样本的位数、采样率)。但是由于我对 MEDIASUBTYPE_WAVE 使用不当导致子类型的差异导致引脚连接失败。当我按照 Roman 的建议将子类型更改为 MEDIASUBTYPE_PCM 后,问题就消失了。