初始化RTSP源过滤器

时间:2011-10-20 08:33:49

标签: streaming directshow rtsp

我有自己的RTSP源过滤器解决方案,目前仍在开发中,但目前正在使用H.264 / MPEG-4视频流。我的问题是在初始化阶段。如果我打开graphedit并逐个添加RTSP源,解码器和视频渲染器并连接它们的引脚,一切正常(RTSP源URL目前是硬编码的)。但是,如果我尝试保存图表并从保存的文件中重新打开图表,图表就会崩溃。我认为原因在于我的RTSP Source Filter的初始化部分。由于我的过滤器在开始时不知道有关流的任何信息,因此它将无效参数传递给解码器。所以,我的问题是:

  • 我应该如何准确处理初始化过程?
  • 何时(代码中的哪个功能)我应该准确连接到源并开始传输?过滤类构造函数?输出引脚类构造函数? OnThreadCreate
  • 我们是否需要从流中获取视频宽度/高度等信息,或者我们是否只需将流传递给解码器?这样做的正确方法是什么? (我认为一些视频渲染器使用VIDEOINFOHEADER结构中的宽度/高度信息。)
  • 我们应该如何确定缓冲区大小?在GetMediaType方法中,我从位图信息标题设置样本大小,如:

    pMediaType-> SetSampleSize(pvi-> bmiHeader.biSizeImage);

我应该如何设置biWidthbiHeightbiSizebiSizeImage等参数?我相信我需要在开头设置一些默认值,然后在收到流后更改它们但是如何?

所有问题都表明同样的问题。我应该在RTSP源过滤器的初始化过程中做些什么?

!UPDATE!

我刚刚注意到,当我加载已保存的图形时,断开连接并重新连接解码器和视频渲染器之间的引脚可以解决问题。我尝试使用不同的视频渲染器(微软和其他一些自定义视频渲染器)。他们都反应相似。其中一些不会崩溃,但运行的视频大小/宽高比不正确。显然,导致图形崩溃或导致奇怪结果的原因不是我的源过滤器,而是传递给视频渲染器的一些无效信息。由于其他RTSP源过滤器不会出现这种情况,我仍然认为我做错了什么,有些东西丢失了。

可能导致此问题的原因是什么?图表开始运行时是否需要发送一些媒体信息?

P.S:图表仅在运行图表时崩溃。只需加载图表不会导致崩溃。

3 个答案:

答案 0 :(得分:3)

如果发生崩溃,则应该在问题发生时出现异常(例如访问冲突)和调用堆栈。这是您从中调试的地方。您可能最终会发现其余部分完全不相关,并且它是由诸如未初始化变量之类的简单事物引起的。

答案 1 :(得分:3)

我同意Wimmel,如果过滤器不支持从保存的图表加载,我没有认为这是一个问题。正如Roman所说,还有两个问题,即需要调试的崩溃和实现问题。

回答你的一些问题:

  • 我应该如何准确处理初始化过程?

    一种方法是实现IFileSourceFilter接口。加载过滤器后,GraphEdit和Windows Media Player都会调用此方法,并允许您执行RTSP DESCRIBE以获取媒体会话描述。对于需要运行流的媒体类型,您还可以播放流,提取宽度和高度等媒体参数,然后正确设置图形。 H264依赖于SDP中通常的序列和图片参数集中的信息。在GetMediaType之前,DS框架将调用IFileSourceFilter :: Load方法,这意味着您的解码器应该被提供正确的参数。

  • 我们是否需要从流中获取视频宽度/高度等信息,还是只需将流传递给解码器?这样做的正确方法是什么? (我认为一些视频渲染器使用来自VIDEOINFOHEADER结构的宽度/高度信息。) 我们应该如何决定缓冲区大小?在GetMediaType方法中,我从位图信息标题设置样本大小,如...

    取决于解码器:某些解码器只需要您流媒体然后正确设置所有内容,其他解码器可能需要正确配置宽度和高度等。如果您使用上述方法,则无关紧要。

您可以在sourceforge下载我们的开源RTSP源过滤器。 它不是商业级RTSP源过滤器,可以处理几种(主要是音频)媒体类型,但它显示了可以帮助您编写自己的各种方面。 IIRC我开始添加H.264支持,使用live555 RTSP服务器的基本测试还可以,但我遇到了一些时间戳H.264流的问题......

另外,我建议使用GraphStudio来测试RTSP源过滤器:如果实现IFileSourceFilter接口,则允许您输入URL。它与GraphEdit非常相似,但我个人更喜欢它。

答案 2 :(得分:2)

如果您的过滤器不完全支持从已保存的图表重新加载,我认为这不是一个大问题。但是不应该崩溃。

首先,我建议搜索崩溃的位置。如果难以使用调试器,只需使用OutputDebugString添加跟踪语句,并使用DebugView查看崩溃前最后执行的内容。例如

HRESULT SetSampleSize(...)
{
    OutputDebugString("SetSampleSize start\n");

    //your code

    OutputDebugString("SetSampleSize exit\n");
}

如果您在跟踪中看到SetSampleSize start,但未看到退出,则表示它在该功能内部崩溃。

如果因为不知道所有参数而无法处理函数,则只返回E_FAIL。我可以想象,如果您不知道收到哪个流,则无法连接引脚。如果未连接引脚,则过滤器将在graphedit中未连接地加载。这比连接错误的格式要好。