草庐IT

windows - DirectShow - 如何从源过滤器中读取文件

coder 2024-06-10 原文

我正在编写一个注册为 CLSID_VideoInputDeviceCategory 的 DirectShow 源过滤器,因此它可以被视为视频捕获设备(例如,从 Skype 中,它被视为另一个网络摄像头)。 我的源过滤器基于来自 here 的 VCam 示例, 现在,过滤器产生与本例完全相同的输出(带有一个视频输出引脚的随机彩色像素,还没有音频),所有这些都是在唯一一个输出引脚的 FillBuffer() 方法中实现的。

现在真实场景会有点棘手 - 过滤器使用硬件设备的文件句柄,使用 CreateFile() API 调用打开(打开设备不在我的控制范围内,由 3Party 库完成).然后它应该从这个句柄中读取数据 block (通常是 256-512 字节的 block 大小)。 该设备是一个 WinUSB 设备,3Party 框架只是“给”我一个打开的文件句柄以从中读取 block 。 过滤器读取的数据是*.mp4 文件,从设备流式传输到“句柄”。

这种情况相当于源过滤器从磁盘上的 *.mp4 文件(以“ block ”形式)读取并将其数据推送到 DirectShow 图形,但无法从头到尾完整地读取文件,所以文件大小未知(正确?)。

我是 DirectShow 的新手,感觉好像缺少一些基本概念。如果有人可以指导我解决以下问题的解决方案\资源\解释,我会很高兴:

1) 从网络上的各种资源和 Microsoft SDK (v7.1) 示例中,我了解到应用程序(例如 Skype)要构建正确且有效的 DirectShow 图(因此它将成功呈现视频和音频),源过滤器引脚(继承自 CSourceStream)应实现方法“GetMediaType”。根据此已实现函数的返回值,应用程序将能够构建正确的图形来呈现数据,从而构建正确的过滤器顺序。如果这是正确的 - 我将如何在我的案例中实现它,以便构建图形以呈现 block 中的 *.mp4 输入(我们可以假设 block 大小不变)?

2) 我注意到 FillBuffer() 方法应该为它获取(和填充)的 IMediaSample 对象调用 SetTime()。我正在从设备读取原始 *.mp4 数据。我是否必须解析数据并从流中提取帧和时间值?如果是 - 一个例子会很棒。

3) 我是否必须将从文件句柄(“ block ”)接收到的数据拆分为视频和音频,或者是否可以将数据推送到图形而不需要在源过滤器中对其进行操作?如果需要拆分 - 如何完成(数据不是连续的,并且被分成 block ),这会影响“GetMediaType”的预期实现吗?

如果我使用的术语不正确,请随时纠正我。

谢谢:-)

最佳答案

这是个好问题。一方面,这是可行的,但涉及到一些具体问题。

首先,您在 CLSID_VideoInputDeviceCategory 类别下注册的过滤器应作为实时视频源。通过这样做,您可以让应用程序(例如您提到的 Skype)发现它,并且这些应用程序将尝试配置视频分辨率,他们希望视频以实时速率播放,某些应用程序(例如 Skype)不希望压缩那里有这样的 H.264 视频,或者只会拒绝这样的设备。您不能将音频直接附加到此过滤器,因为应用程序甚至不会在那里寻找音频(不确定您的过滤器上是否有音频,但您提到了 .MP4 文件,因此音频可能在那里)。

关于您的问题:

1 - 通过检查应用程序调用过滤器的接口(interface)方法,您可以更好地了解应用程序需求。大多数方法由 BaseClasses 实现,并将调用转换为内部方法,例如 GetMediaType。是的,您需要实现它,并且通过这样做,您将 - 除其他外 - 通过尝试您支持的特定媒体类型,使您的过滤器能够与下游过滤器引脚连接。

同样,这些不能用于 MP4 block ,即使这种方法可以在其他 DirectShow 图形中工作。实现视频捕获设备时,您应该提供准确的视频帧,最好是解压缩的(当然也可以压缩,但您将立即遇到与应用程序的兼容性问题)。

您可能会想到的解决方案是在内部嵌入一个功能齐全的图形,您可以在其中注入(inject) MP4 block ,然后管道解析这些图形,解码并传送到您的自定义渲染器,获取您重新曝光的帧你的虚拟设备。这可能是一个不错的设计,但前提是对过滤器的内部工作方式有一定的了解。

2 - 您的设备通常被视为/预期为实时源,这意味着您实时传送视频并且帧不一定带有时间戳。所以你可以把时间放在那里,是的,你肯定需要从你的原始媒体中提取时间戳(或者通过上面第 1 项中提到的内部图表来完成),但是要准备好应用程序剥离时间戳,特别是为了预览目的,因为来源是“直播”。

3 - 回到音频,您不能在同一个虚拟设备上实现音频。嗯,你可以,这个过滤器甚至可以在自定义构建的图形中工作,但这不适用于应用程序。他们将寻找单独的音频设备,如果您实现了这样的设备,他们将单独实例化它。所以你要实现虚拟视频和虚拟音频源,并在幕后实现内部同步。这就是时间戳很重要的地方,通过正确提供它们,您可以在实时 session 中保持口型同步,使其与您正在流式传输的媒体文件中的原始内容保持同步。

关于windows - DirectShow - 如何从源过滤器中读取文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9778114/

有关windows - DirectShow - 如何从源过滤器中读取文件的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  5. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  6. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  9. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  10. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

随机推荐