问题标签 [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 投票
0 回答
226 浏览

delphi - 如何在 DirectShow 多输入音频过滤器中跨输入引脚仲裁流消息?

我正在实现一个 DirectShow 过滤器,它在多个输入引脚之间进行简单的音频混合,并将合并的数据传递到单个输出引脚(多对一)。我已经弄清楚了音频数据混合,但我想对如何处理非媒体数据流消息提出一些意见。例如,下面的代码取自我已经修改并与我的 Delphi 6 应用程序一起使用的 DSPACK DirectShow 组件库:

如您所见,目前我正在将任何不是流媒体数据消息的输入引脚传递立即传递到输出引脚。这与我接收音频数据时所做的相反,我一直保持直到所有输入引脚都传递了它们的下一个音频数据缓冲区,混合该音频数据,然后对我唯一的输出引脚进行单个接收调用。我的问题是:

  1. 在处理音频数据收据时,批处理输入引脚传递会产生什么影响,但会立即将它们传递给非媒体数据收据?可以在此 MSDN 文档中找到此类消息的列表:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd373500(v=vs.85).aspx

  1. 下游过滤器会被这种方法弄糊涂或损坏吗?如果是这样,我应该采用什么技术来仲裁当前连接到混合音频数据的过滤器的输入引脚上的非流媒体数据接收?
0 投票
1 回答
133 浏览

delphi - 我可以安全地假设我的 DirectShow 转换过滤器接收到的目标样本已经分配了内存吗?

我使用 Delphi 6 和 DSPACK 库编写了 DirectShow Transform 过滤器。我检查了 DSPACK 基础过滤器类和属于他们的“WAV Dest”示例应用程序的代码,这是一个转换过滤器示例。据我所知,接收过滤器没有为 Transform 过滤器的源 IMediaSample 或目标 IMediaSample 参数分配内存,尽管我确实看到目标 IMediaSample 的长度可能使用 IMediaSample.SetActualLength() 进行了调整。

我只是想确保我可以依赖调用我的转换过滤器的代码已经为这两个参数分配了内存,所以我不必这样做,如果这确实是 DirectShow API 规范的一部分。否则,我假设我需要自己使用 CoTaskMemAlloc() 进行分配。有人可以在这里给我明确的答案吗?

0 投票
1 回答
642 浏览

delphi - 为什么在与我的 DirectShow Transform 过滤器建立多个输入连接时,DirectShow 会拖入不必要的中间过滤器?

我有一个使用 DSPACK 组件库用 Delphi 6 编写的 DirectShow Transform 过滤器。它是一个简单的音频混音器,每当尝试新连接时,它都会创建一个新的输入引脚。我说很简单,因为一旦设置了它的媒体格式,所有到它的输入引脚或单个输出引脚的连接都被迫符合该媒体格式。我手动构建过滤器链,我自己明确地进行所有引脚连接。我不使用任何“智能渲染”调用,除非有某种方法可以意外触发这种不需要的行为(在我的情况下)。

注意:捕获过滤器是我的应用程序外部的标准 DirectShow 过滤器。我的推送源音频过滤器和简单的混音器过滤器被用作私有的、未注册的过滤器,并且在我的应用程序内部。

我遇到了一个奇怪的问题,只有当我尝试与我的混音器建立多个输入连接时才会出现这种问题,它确实接受了它们。目前,我正在尝试将捕获过滤器和我的自定义推送源音频过滤器连接到我的混音器过滤器。每当我尝试这样做时,第二个上游过滤器连接都会失败。无论我是先连接捕获过滤器还是先推送源音频过滤器,第二个上游过滤器连接总是失败。

我运行的第一个测试是尝试仅将 Capture Filter 连接到混音器。那工作得很好。

我运行的第二个测试是尝试仅将 Push Source 音频过滤器连接到混音器。那工作得很好。

但是,一旦尝试同时执行这两项操作,我就会收到“找不到中间过滤器的组合”错误。我做了几个小时的深入挖掘媒体协商调用,从图形生成器点击我的过滤器,然后我发现了问题。出于某种原因,过滤器图正在将古老的“ Indeo (R) Audio Software ”编解码器拖入链中。

我发现了这一点,因为尽管编解码器确实有一个媒体格式在几乎所有方面(主要类型、子类型、格式类型、波形格式参数)都与我的过滤器匹配,但它在 pbFormat 数据的末尾有一个额外的 2 个字节成员,这足以让equals失败测试,因为该测试通过比较每种媒体类型的 cbFormat 值来比较源和目标 pbFormat 区域。Indeo 编解码器的 cbFormat 值为 20,而我的过滤器的 cbFormat 值为 18,这是 _tWAVEFORMATEX 数据结构的大小。在某种程度上,Indeo pbFormat 具有这种奇怪的大小是一件好事,因为它的 20 字节区域的前 18 个字节正好等于我的混音器过滤器支持的媒体类型的 pbFormat 区域。如果没有这种异常,我永远不会知道古代编解码器正在被吸毒。我很惊讶它完全被吸毒了,因为它已经知道了漏洞利用和漏洞。最令人困惑的是,这发生在我的混频器滤波器的输出引脚上,而不是输入引脚之一,并且在建立我的引脚连接时,我还没有建立一个下游连接。

谁能告诉我为什么 DirectShow 试图拖入该编解码器,尽管事实上两个传入过滤器、捕获过滤器和推送源过滤器的媒体格式是相同的,并且根本不需要任何中间过滤器,因为它们匹配我的混音器过滤器的输入引脚完全支持格式吗?我该如何解决这个问题?

另外,我注意到即使在上面的单个过滤器附件测试中成功,我的混音器输出引脚仍然被查询媒体格式。为什么正如我所说,在建立我的引脚连接时,我没有将任何东西连接到混频器滤波器的输出引脚?

--------------------------------------- 更新:1 -------- --------

我了解到您可以通过使用 IFilterGraph.ConnectDirect() 而不是 IGraphBuilder.Connect() 完全避免“智能连接”行为。我切换到 DirectConnect(),结果我的混音器过滤器上的输入引脚返回为“已连接”。这可能是导致图形生成器拖入 Indeo 编解码器过滤器的原因。现在我有了这个新的诊断信息,我将更正问题并用我的结果更新这篇文章。

0 投票
1 回答
977 浏览

delphi - 什么可能导致 DirectShow 推送源过滤器以比预期更快的速度推送数据?

在 DSPACK 组件库的帮助下,我有一个 DirectShow 推送源过滤器和一个 DirectShow 简单音频混合器过滤器,它们都是用 Delphi 6 编写的。在我的应用程序中,我手动构建了一个过滤器图,对于引脚连接,我使用 IFilterGraph.ConnectDirect() 来避免来自 DirectShow 的“智能连接”技术的任何干扰。我将这两个过滤器用作程序内部的私有/未注册过滤器。

我构建的图表有一个捕获过滤器和我的推送源音频过滤器共享图表的头部位置。它们的输出引脚连接到我的简单音频混音器,后者支持多个输入连接。混音器强制其输入和输出引脚的所有连接与其构造函数中预设的媒体格式类型完全相同。在这种情况下,我使用的格式设置是 WAV 格式,采样率为 8000,每个采样 16 位,一个通道。请注意,我使用 DecideBufferSize() 将所有过滤器设置为 50 毫秒的缓冲区大小。这导致交付的缓冲区大小为 400 字节(200 个样本)。

捕获过滤器是我使用 DirectShow API 找到的外部 COM 对象。目前我正在将我的 VOIP 电话分配为设备(Moniker)。出于某种奇怪的原因,我的推源过滤器以恰好是捕获过滤器的 7 倍的速率抽出缓冲区。换句话说,我的混频器过滤器从我的推送源过滤器中获取 7 个缓冲区,用于从捕获过滤器接收到的每个缓冲区。我知道这一点,因为每次混合器过滤器获得缓冲区时我都会调试打印一行,并且我识别出作为缓冲区源的过滤器。

我不知道捕获过滤器是如何形成其时间戳的,因为它是外部代码,但我希望它是通常的方案。我的推送源过滤器从零开始,每次 FillBuffer() 调用都会将 DirectShow 参考时间格式的时间戳增加缓冲区表示的时间量。

以下是我的问题:

1)如果我手动构建图表,时间戳是否重要?即使您完全手动构建图形,DirectShow 是否会介于过滤器之间,并且会以某种方式影响引脚写入(接收呼叫)的时间?

2) 什么常见的错误会导致过滤器过快推出缓冲区,尽管图形周围的媒体格式是同质的?

0 投票
2 回答
1695 浏览

delphi - 尽管输出文件“平滑”,但在渲染我的 DirectShow 过滤器期间出现口吃

我有一个使用 DSPACK 组件库用 Delphi 6 编写的 DirectShow 应用程序。我有两个相互合作的过滤器图。

过滤器图具有以下结构:

  1. 具有 100 ms 缓冲区大小的捕获过滤器。
  2. (连接到)样品采集过滤器。

“二级”过滤器图具有这种结构。

  1. 自定义推送源过滤器,将音频直接接收到它管理的音频缓冲区仓库。
  2. (连接到)渲染过滤器。

Push Source Filter 使用事件来控制音频的传递。它的 FillBuffer() 命令等待事件。当新的音频数据添加到缓冲区时,会发出事件信号。

当我运行过滤器图表时,我听到音频中有微小的“间隙”。通常我会将这种情况与构造不正确的音频缓冲区联系起来,这些缓冲区没有被填充或在其中有“间隙”。但作为测试,我添加了一个 Tee 过滤器并连接了一个 WAV Dest 过滤器,然后是一个 File Writer 过滤器。当我检查输出 WAV 文件时,它非常平滑且连续。换句话说,我从扬声器听到的间隙在输出文件中并不明显。

这表明尽管来自 Capture Filter 的音频传播成功,但音频缓冲区的传递却受到周期性干扰。我听到的“间隙”不是每秒 10 次,而是每秒 2 或 3 次,有时甚至是短时间根本没有间隙。所以不是每个缓冲区都发生这种情况,否则我会听到每秒 10 次的间隙。

我的第一个猜测是它是一个锁定问题,但我在 150 毫秒的事件上设置了超时,如果发生这种情况,则会引发异常。没有抛出异常。我还在应用程序中使用的每个关键部分设置了 40 毫秒的超时,并且这些部分都没有触发。我检查了我的 OutputDebugString() 转储以及非信号(阻塞)和信号之间的时间(未阻塞的)事件显示了在 94 毫秒和 140 毫秒之间交替的相当恒定的模式。换句话说,我的 Push Source Filter 中的 FillBuffer() 调用保持阻塞 94 毫秒,然后是 140 毫秒,然后重复。请注意持续时间有点漂移,但它很规律。考虑到 Windows 线程切换的变幻莫测,这种模式似乎与等待捕获过滤器的线程以 100 毫秒的间隔将其音频缓冲区转储到推送源过滤器的线程一致。

我在我的推送源过滤器中使用了双缓冲,所以我相信如果没有一个锁定机制花费 200 毫秒或更多的组合时间,我不应该中断音频流。但我想不出除了会导致这些症状的锁定问题之外的其他任何事情。我在下面的推送源过滤器中包含了我的 DecideBufferSize() 方法的代码,以防我做错了什么。虽然它有点冗长,但我还在下面包含了 FillBuffer() 调用,以显示我如何生成时间戳,以防万一可能产生影响。

尽管所有音频缓冲区都完好无损地传递,还有什么可能导致我的渲染过滤器的音频流口吃?

问题:我必须自己实现双缓冲吗?我认为 DirectShow 渲染过滤器会为您做到这一点,否则我在没有自定义推送源过滤器的情况下创建的其他过滤器图将无法正常工作。但也许因为我在过滤器图中创建了另一个锁定/解锁情况,我需要添加我自己的双缓冲层?我当然想避免这种情况以避免额外的延迟,所以如果我的情况有其他解决方法,我想知道。

0 投票
1 回答
279 浏览

delphi - 为什么我会从具有相同采样时间的 DirectShow 捕获过滤器中获取连续的媒体样本?

我有一个使用 DSPACK 组件库在 Delphi 6 中编写并在 Windows XP 上运行的 DirectShow 应用程序。我的过滤器图的顶部是一个音频捕获过滤器。捕获过滤器已分配给我的 VOIP 电话,并且在流中立即有一个样本采集器过滤器。在样本采集过滤器的回调方法中,每当我从样本采集过滤器连续获得两个具有相同时间戳(SampleTime)的媒体样本时,我都会添加代码来报告。这种情况经常发生,有时几乎每次都发生。请注意,捕获过滤器的缓冲区大小为 100 毫秒,采样率为 8000 kHz。逻辑告诉我,我永远不应该得到两个具有相同采样时间的样品交付,并且它们应该总是相隔非常接近 100 毫秒。但事实并非如此。

当 DirectShow 捕获过滤器向您发送 2 个具有相同采样时间的连续媒体样本时,这意味着什么?我应该忽略与前一个样品时间相同的第二个样品交付吗?还是在某个地方我需要解决另一个问题?

请注意,我无法控制进入我的采样时间。它们是由捕获过滤器生成的。

0 投票
1 回答
226 浏览

delphi - 我什么时候需要担心锁定 DirectShow 过滤器的共享状态?

我有一个使用 DSPACK 组件库的 Delphi 6 DirectShow 推送源视频过滤器。过滤器的哪些方面需要我在执行某些操作之前锁定过滤器状态?例如,在我的过滤器的 FillBuffer() 方法中,我是否需要在编写位图画布之前锁定过滤器的共享状态?还是只有过滤引脚连接/断开事件或媒体格式协商等操作需要锁定共享状态?

0 投票
1 回答
342 浏览

delphi - 在过滤器关闭时,我可以使用什么 Directshow 过滤器事件来解除对源流线程的阻塞?

我有一个使用 DSPACK 组件库用 Delphi 6 编写的 DirectShow 过滤器。它是一个推源视频过滤器。过滤器阻塞在另一个生成视频帧的线程中发出的事件。当一个帧准备好时,它被写入一个共享内存区域,FillBuffer() 方法在它被解除阻塞时访问该区域。当过滤器被 DirectShow 关闭时,是否有一个方便的 DirectShow 事件可以让我解除阻塞 FillBuffer() 线程?如果不是,这方面的“标准做法”是什么?

0 投票
1 回答
1338 浏览

delphi - 如果在主机选项卡不可见时图形启动,DirectShow 渲染窗口显示黑色 (TVideoWindow)

我有一个使用 DirectShow DSPACK 组件套件的 Delphi 6 应用程序。它有一个 TVideoWindow 组件,可以从过滤器图中渲染图像。TVideoWindow 组件位于页面组件的选项卡上。如果在我运行过滤器图表时选项卡可见,则视频显示得很好。另外,我可以切换到另一个选项卡并回来,视频仍然很好。但是,如果我在选项卡不可见时运行过滤器图表,那么当我切换到该选项卡时,视频窗口区域为黑色。我尝试切换到另一个选项卡并返回,最小化主机表单并恢复它,它保持黑色。我想知道这是否是窗口/组件句柄生命周期问题?我怎样才能解决这个问题?

0 投票
1 回答
823 浏览

delphi - 为什么将渲染器添加到我的 DirectShow 过滤器图形会平滑图形的音频输入?

我在使用 DSPACK 组件库构建的 Delphi 6 应用程序中有一个 DirectShow 过滤器图。图的结构如下:

  • 自定义推送源音频过滤器
  • 样品采集器
  • Tee 过滤器(但仅当我同时打开 WAV 文件编写器和渲染器时)
  • 渲染器(首选 PC 输出设备)
  • WAV 文件编写器

仅当我同时打开了 Renderer 和 WAV File Writer 过滤器时,才会将 Tee 过滤器添加到图表中。否则,我只将直接打开的过滤器连接到 Sample Grabber

音频通过 WiFi 连接的 RTSP 音频服务器传输,该服务器实时传输音频。如果我打开 Wav 文件编写器,我的耳机发出的音频会出现与无缓冲音频流相关的典型抽吸声和偶尔的咔嗒声。奇怪的是,只要我打开 WAV File Writer 过滤器,音频就会变得像玻璃一样平滑。

我有 WAV 文件编写器的源代码,它基本上处理在需要时输出正确的 WAV 文件头并在必要时写入音频缓冲区的任务,仅此而已。所以我觉得奇怪的是,打开它会平滑传入的音频流,特别是因为它不是渲染器(过滤器)的上游,而是一个对等过滤器,它悬挂在渲染器旁边的 Tee 过滤器的末端。

当我打开 File Writer 过滤器时,谁能告诉我会发生什么以使音频传输顺畅?三通过滤器是否有任何固有的缓冲作用?我想复制相同的机制,以便在未打开文件写入器时获得流畅的音频。我试图避免添加我自己的缓冲,因为我不想给实时音频流增加任何延迟。