问题标签 [dspack]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
2799 浏览

delphi - 如何消除 DirectShow 过滤器链中的 1 秒延迟?(使用 Delphi 和 DSPACK)

我有一个 Delphi 6 Pro 应用程序,它使用 DSPACK 组件库从系统的首选音频输入设备向 Skype 发送音频。我正在使用 TSampleGrabber 组件来接入过滤器图链,然后将音频缓冲区发送到 Skype。问题是我每秒只能获得一次音频。换句话说,TSampleGrabber 实例的 OnBuffer() 事件每秒仅触发一次,Buffer 参数中包含一整秒的数据。我需要知道如何修改我的过滤器图链,以便它以比每秒一次更快的间隔从输入设备获取数据。如果可能的话,我希望每 50 毫秒或至少每 100 毫秒快一次。

我的过滤器图链由一个 TFilter 组成,它映射到顶部的系统首选音频输入设备。我将该滤波器的输出引脚连接到分配了“WAV Dest”的 TFilter 的输入引脚,这样我就可以获得 PCM WAV 格式的样本。然后,我将“WAV Dest”过滤器的输出引脚连接到 TSampleGrabber 实例的输入引脚。我需要更改什么才能让 TSampleGrabber OnBuffer() 事件以更快的间隔触发?


更新:根据 Roman R 的回答,我能够实现我在​​下面展示的解决方案。一注。他的链接将我带到以下对解决方案有帮助的博客文章:

http://sid6581.wordpress.com/2006/10/09/minimizing-audio-capture-latency-in-directshow/

0 投票
1 回答
622 浏览

delphi - 仅提供音频的 DirectShow 推送源过滤器的正确样本大小是多少?

我有一个使用 DSPACK 库的 Delphi 6 Pro 程序来执行 DirectShow 过滤器工作。我正在创建我的第一个推送源过滤器,它将提供来自自定义音频源的音频。目前我最大的问题是如何确定在 FillBuffer() 调用期间我将复制到过滤器的输出缓冲区中的数据量。

我真的一次只复制一个音频样本吗?在我的情况下,这将只有 2 个字节,因为每个音频样本都是 16 位宽的单通道。这似乎效率极低。还是我一次复制一个样本块,如果是这样,确定要复制多少字节的正确逻辑是什么?简单地使用 Sample.GetSize() 返回的值作为要提供的字节数是否是正确的逻辑,其中 Sample 是传递给 FillBuffer() 调用的 IMediaSample 对象?

此外,如果有人对创建音频推送源过滤器和视频过滤器有任何提示或注意事项,请在此处发布。我正在使用的示例是一个视频过滤器,它将当前桌面图像作为一系列位图流式传输。我担心当使用视频过滤器作为我的起点时,我会做一些不适合纯音频 DirectShow 过滤器的事情。此外,来自此过滤器的音频必须是实时的,因为它涉及两方之间的实时音频连接。

0 投票
1 回答
759 浏览

delphi - 如何正确构建私有又名未注册的 DirectShow 过滤器(有源代码)?

我使用 Delphi 6 Pro 和 DSPACK DirectShow 组件库创建了一个推送源过滤器。我想私下使用过滤器,所以我不会为 DLL 创建 AX 文件。相反,我想直接创建过滤器。我在这方面找到了一些线程,但它们都没有显示如何在给定过滤器的构造函数的情况下构造私有过滤器:

以下是我在未注册或私有 DirectShow 过滤器主题上找到的一些主题:

http://www.gdcl.co.uk/2011/June/UnregisteredFilters.htm

http://www.progdigy.com/forums/viewtopic.php?p=12304&sid=df52f07f5b00d7ebfac12cb9b9bd9b54

如何在 EXE 中直接嵌入 DirectShow Push Source 过滤器?

Filter 的源代码已直接添加到我的 Delphi 项目中。但是我不知道直接从我的主应用程序创建过滤器时应该使用哪个构造函数,以及为构造函数的参数传递什么。有人能告诉我他们应该是什么吗?

另外,我是否需要像上面第一个线程所说的那样增加 Filter 对象的引用计数,然后在我的应用程序终止时对其调用 Release() ?如果是这样,最好的方法是什么?或者我可以在我的应用程序终止时在过滤器上调用 Free 吗?

最后,在使用我的私有过滤器之前,我需要调用 CoInitialized() 和 CoUninitialize() 吗?

更新:通过 TBCSource(DSPACK 派生过滤器的基类)的类和类层次构造函数链进行跟踪,似乎ObjName参数是过滤器名称,而Unk参数是拥有过滤器的对象。我目前的猜测是,直接从源创建过滤器的正确方法是,给定一个名为 TPushSourceFilter 的 TBCSource 派生类,任意给定过滤器名称“我的推送源过滤器”,例如:

第一个构造函数参数是用于注册过滤器的过滤器名称,即您在 GraphEdt 之类的工具中细读 DirectShow 过滤器时看到的名称。我认为第二个参数应该是 NIL,因为它解析为名为 TBCUnknown 的祖先类中的所有者数据字段 (FOwner)。它的唯一目的是将基类处理的任何 QueryInterface() 调用重定向到所有者对象(如果它是非 NIL),而不是将查询直接应用于 Filter 对象以防它是委托情况。我将继续使用这种构造方法,看看它是否有效。

0 投票
2 回答
758 浏览

delphi - 在 DirectShow Filter 的 EnumPins 方法 (Delphi/DSPACK) 中处理 NULL ppPins 参数的正确方法?

我在 Windows XP/32 机器上使用 DSPACK DirectShow 组件库在 Delphi 6 中编写了一个自定义推送源过滤器。在编码期间,在我的应用程序编译器选项中打开范围检查后,我遇到了属于 DSPACK (BaseClass.pas) 的BaseClass单元中发生范围检查错误的问题。

该错误发生在我的 EnumPins() 方法期间。请注意,此方法驻留在 DSPACK 的 BaseClass 单元中,而不是我的应用程序中。我跟踪了问题并发现它发生在我构建的使用我的过滤器的过滤器图播放过滤器时。请注意,我的过滤器作为私人未注册过滤器直接合并到我的应用程序中,而不是作为外部 AX。当 DirectShow 调用基类方法TBCEnumPins.Next()时,如果ppPins参数为NIL然后发生范围检查错误。由于我不是 DirectShow 专家,我不确定在不干扰 DirectShow 引脚枚举过程的正常流程的情况下修复此错误的正确方法是什么。相反,如果这是一个不可忽略的真正错误条件,那么我需要知道在此事件中要抛出的正确异常或要返回的 HRESULT 代码是什么。谁能告诉我为 NIL ppPins 参数调整此代码的正确方法?完整的方法代码如下,其中出现范围检查错误的行突出显示:

更新:从技术角度来看,DSPACK 代码似乎是合理的,但从编码习惯的角度来看有点奇怪,并且其结构与范围检查不兼容。通过 ppPins“out”参数传入的 NIL 映射到调用者作为 ppPins 参数传递给 TBCEnumPins.Next() 的目标缓冲区。例如,下面的代码来自这个页面:

http://tanvon.wordpress.com/2008/09/07/enumerating-the-directshow-filter-pin/

在该页面上是以下代码,它与 DirectShow 过滤器交互以枚举过滤器的引脚:

通过告诉 Next() 方法要检索多少个引脚,TBCEnumPins.Next() 方法代码及其不寻常的动态数组强制转换是安全的,因为它只会复制到 ppPins“out”参数中的引脚数在 Next() 函数“cPins”参数中请求。只要调用者传递一个可以保存“cPins”中请求的引脚数量的目标缓冲区,一切都可以正常工作(只要关闭范围检查)。请注意,在这种情况下,名为“outPin”的 IPin 变量是目标缓冲区。如果打开范围检查,则会发生范围检查错误,因为 Delphi 将 NIL 视为零长度数组。

0 投票
1 回答
422 浏览

delphi - 如果过滤器具有持久的本地数据,我是否需要每个 DirectShow 过滤器实例的唯一类 ID?

我编写了一个推送源过滤器,我在我的 Delphi 6 应用程序中私下使用它。该应用程序使用 DSPACK DirectShow 组件库。私下我的意思是我只是将过滤器的实例直接添加到我的过滤器图表中,而不是驻留在外部 DLL(.ax文件)中的过滤器。

我应该为我创建的每个过滤器实例创建一个唯一的类 ID (GUID),还是在创建的所有实例之间使用相同的类 ID 是否安全?我担心这一点,因为过滤器的每个实例都会创建一个本地数据存储对象,用于保存为过滤器排队的数据。本地数据存储对象由主机应用程序中的其他代码写入,从而通过我的推送源过滤器将数据推送到过滤器图中。

我现在对 DirectShow 还不够了解如何进行方法指针查找以了解我的设计是否安全。当我直接将过滤器的实例添加到图形时,DirectShow 是否存储过滤器图形将通过对象引用或类 ID 调用的接口方法指针?如果是前者,那么一切都会好起来的,但如果是后者,那么如果同一个实例获得所有方法调用,那可能是个问题。有人知道这个设计问题的答案吗?

0 投票
3 回答
1486 浏览

delphi - 尽管它是 QueryPinInfo 返回的 ID,但无法按名称/ID 在 DirectShow 过滤器中找到 pin

我在开发 DirectShow 应用程序时遇到了一个奇怪的问题。我正在使用带有 DSPACK DirectShow 组件库的 Delphi 6。当我尝试使用它的 TPinInfo.achName 属性 (_PinInfo) 在过滤器中查找引脚时,其中一个 IBaseFilter 实例似乎无法识别它拥有的引脚。(注意,在这种情况下,是由 TSampleGrabber 组件创建的 IBaseFilter 表现出这种奇怪的行为)。

事件序列,封装在下面的代码示例中是这样的:

  1. 在 IBaseFilter 实例中找到第一个可用的输入引脚。在下面的代码中,这是传递给 testPinInfo() 的引脚。
  2. 对返回的 pin 执行 QueryPinInfo() 以获取该信息。返回的信息将引脚的 achName 显示为“输入”。
  3. 尝试使用 IBaseFilter.findPin() 在同一个 IBaseFilter 实例中找到一个名为“Input”的引脚。
  4. 返回 NIL 表示找不到具有该名称的引脚。在我看来,这是一个非常奇怪的情况(错误)。

有谁知道什么样的条件会导致这种情况?我不认为这是一个内存损坏问题,因为当我在调试器中检查它们时,所涉及的数据结构看起来很好。是否有可能某些 IBaseFilter 实现忽略了正确实现 FindPin() 方法?

下面是代码:

0 投票
1 回答
2315 浏览

delphi - 如何在捕获过滤器的 DirectShow put_Enable 调用期间调试未指定的错误 ($80004005)?

我有一个使用 DSPACK 组件库用 Delphi 6 编写的 DirectShow 应用程序。我在启用过滤器上的输入行时遇到了一个奇怪的问题。我搜索引脚,直到找到输入线,在本例中名为“麦克风”,并在过滤器图处于活动状态时对其调用 put_Enable(true)。当我这样做时,我得到一个 $80004005 的“未指定错误”作为 HRESULT。

在启用输入线之前,我正在为过滤器设置输出音频媒体类型,但有些东西无法正常工作。我用来创建应用程序的原始 DirectShow 示例运行良好。我相信我正在按照完全相同的步骤构建我的过滤器图,当然我可能错过了一些东西。有人对我可以尝试解决此问题的事情有任何提示或想法吗?下面的代码片段部分显示了我正在做的事情,但不是所有导致它的步骤,因为它们非常冗长。我用于测试的捕获设备是一个 VOIP 耳机,带有一条名为“麦克风”的输入线。

0 投票
1 回答
1594 浏览

delphi - DirectShow“找不到中间过滤器的组合”错误的其他原因?

我有一个使用 DSPACK DirectShow 组件库的 Delphi 6 应用程序。目前,当我尝试将音频捕获设备上的捕获引脚连接到另一个过滤器的输入引脚时,我收到错误“找不到中间过滤器的组合”。我相信我正确设置了媒体格式。我有一个错误陷阱,在该陷阱中,我明确地查询两个引脚以获取它们设置的确切媒体格式,以防出现不一致。当我这样做时,两个引脚都以完全相同的 WAV 格式返回:

格式标签:1

通道数:1

每个样本的位数:16

采样率:8000

这与我将两个过滤器设置为的匹配,但我收到一个错误(通常据我所知)表明格式不兼容。有没有人遇到过这个错误并且知道我可能做错了什么或者我可以做哪些其他类型的测试/检查?

0 投票
1 回答
155 浏览

delphi - 是否有一种自动方法来防止“陈旧”的 DirectShow 接口引用?

我刚刚有一个很长的调试会话,这是由使用 DSPACK 组件库的 Delphi 6 DirectShow 应用程序中的“陈旧”接口引用引起的。如您所知,当过滤器图处于活动状态时需要执行一些操作,而当过滤器图必须处于非活动状态时,需要对组件参数执行其他操作。问题是您最终可能会得到仍然具有初始化值(已分配,而不是 NIL)的 DirectShow 接口引用,但对于当前的 Filter Graph 化身无效,因为它们是在 Filter Graph 的先前化身期间创建的。在打开和关闭过滤器图以在“实时”发现操作和离线配置操作之间切换时,这并不难做到。

例如,您可能有一个 IBaseFilter 引用,该引用是您在第一次激活过滤器图时分配的,您在停用和重新激活过滤器图后尝试重新使用该引用。接口引用现在是“陈旧的”,因为它不属于 Filter Graph 的当前化身,而是属于以前的化身。这会导致各种奇怪且不直观的 DirectShow 错误消息,这些错误消息并不是它们看起来的那样,但实际上是由于接口引用过时造成的。

有没有人想出一种方法,无论是通过约定还是通过一些聪明的解决方案,例如与过滤器图的生命周期相关的 DirectShow 智能指针等,以防止这种情况发生?或者是唯一对接口引用使用保持谨慎的解决方案?

0 投票
1 回答
511 浏览

delphi - 是否有一个简单的 DirectShow 过滤器可以将完全相同格式的音频混合在一起?

我有一个使用 DSPACK 组件库用 Delphi 6 编写的 DirectShow 应用程序。我希望能够将来自多个捕获过滤器的输出引脚的音频混合在一起,这些捕获过滤器设置为完全相同的媒体格式。是否有这样做的开源或“sdk 示例”过滤器?

我知道智能混音很重要,而且我很可能必须购买商业图书馆才能做到这一点。但我只需要一个 DirectShow 过滤器,它可以接受来自多个输出引脚的波形音频输入,并直接添加接收到的样本。我知道有用于将单个流拆分为多个流(一对多)的 Tee 过滤器,但我需要一些相反的东西(多对一),最好对每个输入连接尝试进行格式检查,以便任何尝试使用与已添加的媒体格式不同的媒体格式附加输出引脚会因错误而受阻。外面有什么吗?